kernel: Update 4.10 tree

Move to 4.10.17. This incorporates all of the 4.10 stable fixes. 4.10 is
now end of lifed and does not receive further fixes.

New drivers:
 - LPC snoop
 - OCC SBE
 - SBE FIFO
 - Infineon IR35221
 - Maxim MAX31785
 - of_serial reset support
 - Aspeed PWM and fan tach driver
 - UCHI driver
 - FSI device tree match support

New platforms:
 - Mellanox MSN BMC

Config and device tree changes:
 - Enable VMSPLIT_2G for ast2400. This is allows us to map all of the
   mtd flash
 - Fix device trees for ast2400 mtd support
   Resolves openbmc/openbmc#1686
 - Add CFAM layout to device tree
   Resolves openbmc/openbmc#1697
 - Enable new drivers

[the content below is for the changes made in c13af44db76bd1 and are
included so that the details are in openbmc history]

This is OpenBMC's third major kernel change. We now move to a 4.10 base,
where a larger amount of our driver support has been upstreamed.

 - NCSI stack
 - IRQ driver
 - Watchdog driver
 - Clocksource driver
 - GPIO driver
 - Pinmux driver
 - ftgmac100 ast2500 support
 - IPMI BT driver
 - adm1275 driver fix

In addition, this contains backports of a significant amount of work
that was done post-4.10.

 - LPC bindings
 - Pinctrl enhancements
 - Flash controller (spi-nor) basic support
 - ast2500 GPIO support
 - LPC host interface controller driver
 - Aspeed ADC
 - GPIO debounce support
 - Pinconf (biasing and drive strength) driver

Finally, there is the work-in-progress that has been temporarly staged
in the dev tree while we get it reviewed and upstreamed.

 - New I2C driver
 - OCC driver
 - LPC mailbox driver
 - FSI core
 - VUART driver

Defconfig updates
 - Optmise options for network performance
 - Update for upstreamed drivers (MTD driver was renamed, etc)
 - Enable drivers that are in use

Legacy Yocto layer changes
 - Remove palmetto GPIO hog patch. It is in the kenrel tree

Change-Id: I4b48b843572c8f8d547763f0d3cb5a6742bbf0e3
Signed-off-by: Joel Stanley <joel@jms.id.au>
diff --git a/common/recipes-kernel/linux/linux-obmc.inc b/common/recipes-kernel/linux/linux-obmc.inc
index fe07680..78da469 100644
--- a/common/recipes-kernel/linux/linux-obmc.inc
+++ b/common/recipes-kernel/linux/linux-obmc.inc
@@ -10,18 +10,6 @@
 SRC_URI = "${KSRC}"
 SRC_URI += "file://phosphor-gpio-keys.scc"
 SRC_URI += "file://phosphor-gpio-keys.cfg"
-SRC_URI += "file://0001-fsi-Match-fsi-slaves-engines-to-available-device-tre.patch"
-SRC_URI += "file://linux-dev-4.10-v2-1-6-drivers-i2c-Add-FSI-attached-I2C-master-algorithm.patch"
-SRC_URI += "file://linux-dev-4.10-v2-2-6-drivers-i2c-Add-port-structure-to-FSI-algorithm.patch"
-SRC_URI += "file://linux-dev-4.10-v2-3-6-drivers-i2c-Add-transfer-implementation-for-FSI-algorithm.patch"
-SRC_URI += "file://linux-dev-4.10-v2-4-6-drivers-i2c-Add-I2C-master-locking-to-FSI-algorithm.patch"
-SRC_URI += "file://linux-dev-4.10-v2-5-6-drivers-i2c-Add-bus-recovery-for-FSI-algorithm.patch"
-SRC_URI += "file://linux-dev-4.10-drivers-fsi-Add-FSI-SBEFIFO-driver.patch"
-SRC_URI += "file://linux-dev-4.10-1-3-drivers-fsi-sbefifo-Add-in-kernel-API.patch"
-SRC_URI += "file://linux-dev-4.10-2-3-drivers-fsi-sbefifo-Add-OCC-driver.patch"
-SRC_URI += "file://0001-arm-dts-aspeed-Add-FSI-devices.patch"
-SRC_URI += "file://0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch"
-SRC_URI += "file://v2-0001-arm-dts-aspeed-Add-missing-clock-sources-for-barr.patch"
 
 LINUX_VERSION_EXTENSION ?= "-${SRCREV}"
 
diff --git a/common/recipes-kernel/linux/linux-obmc/0001-arm-dts-aspeed-Add-FSI-devices.patch b/common/recipes-kernel/linux/linux-obmc/0001-arm-dts-aspeed-Add-FSI-devices.patch
deleted file mode 100644
index 3b49685..0000000
--- a/common/recipes-kernel/linux/linux-obmc/0001-arm-dts-aspeed-Add-FSI-devices.patch
+++ /dev/null
@@ -1,507 +0,0 @@
-From e45cd4677a36eb759537f59c5f5bcf46b91728b3 Mon Sep 17 00:00:00 2001
-From: "Edward A. James" <eajames@us.ibm.com>
-Date: Mon, 15 May 2017 11:02:48 -0500
-Subject: [PATCH linux dev-4.10] arm: dts: aspeed: Add FSI devices
-
-using Jeremy's new bindings
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts    |  75 ++++++++++
- arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts | 181 +++++++++++++++++++++++
- arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts       | 181 +++++++++++++++++++++++
- 3 files changed, 437 insertions(+)
-
-diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
-index b4faa1d..6f23ce3 100644
---- a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
-+++ b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
-@@ -85,12 +85,87 @@
- 
- 	gpio-fsi {
- 		compatible = "fsi-master-gpio", "fsi-master";
-+		#address-cells = <2>;
-+		#size-cells = <0>;
- 
- 		clock-gpios = <&gpio ASPEED_GPIO(A, 4) GPIO_ACTIVE_HIGH>;
- 		data-gpios = <&gpio ASPEED_GPIO(A, 5) GPIO_ACTIVE_HIGH>;
- 		mux-gpios = <&gpio ASPEED_GPIO(A, 6) GPIO_ACTIVE_HIGH>;
- 		enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
- 		trans-gpios = <&gpio ASPEED_GPIO(H, 6) GPIO_ACTIVE_HIGH>;
-+
-+		cfam@0,0 {
-+			reg = <0 0>;
-+			#address-cells = <1>;
-+			#size-cells = <1>;
-+
-+			i2c-master@1800 {
-+				compatible = "ibm,fsi-i2c-master";
-+				reg = <0x1800 0x400>;
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+
-+				port@0 {
-+					port = <0>;
-+				};
-+
-+				port@1 {
-+					port = <1>;
-+				};
-+
-+				port@2 {
-+					port = <2>;
-+				};
-+
-+				port@3 {
-+					port = <3>;
-+				};
-+
-+				port@4 {
-+					port = <4>;
-+				};
-+
-+				port@5 {
-+					port = <5>;
-+				};
-+
-+				port@6 {
-+					port = <6>;
-+				};
-+
-+				port@7 {
-+					port = <7>;
-+				};
-+
-+				port@8 {
-+					port = <8>;
-+				};
-+
-+				port@9 {
-+					port = <9>;
-+				};
-+
-+				port@10 {
-+					port = <10>;
-+				};
-+
-+				port@11 {
-+					port = <11>;
-+				};
-+
-+				port@12 {
-+					port = <12>;
-+				};
-+
-+				port@13 {
-+					port = <13>;
-+				};
-+
-+				port@14 {
-+					port = <14>;
-+				};
-+			};
-+		};
- 	};
- };
- 
-diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts b/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
-index f20aaf4..5d83a76 100644
---- a/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
-+++ b/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
-@@ -65,6 +65,8 @@
- 
- 	gpio-fsi {
- 		compatible = "fsi-master-gpio", "fsi-master";
-+		#address-cells = <2>;
-+		#size-cells = <0>;
- 
- 		status = "okay";
- 
-@@ -73,6 +75,185 @@
- 		mux-gpios = <&gpio ASPEED_GPIO(A, 6) GPIO_ACTIVE_HIGH>;
- 		enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
- 		trans-gpios = <&gpio ASPEED_GPIO(R, 2) GPIO_ACTIVE_HIGH>;
-+
-+		cfam@0,0 {
-+			reg = <0 0>;
-+			#address-cells = <1>;
-+			#size-cells = <1>;
-+
-+			i2c-master@1800 {
-+				compatible = "ibm,fsi-i2c-master";
-+				reg = <0x1800 0x400>;
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+
-+				port@0 {
-+					port = <0>;
-+				};
-+
-+				port@1 {
-+					port = <1>;
-+				};
-+
-+				port@2 {
-+					port = <2>;
-+				};
-+
-+				port@3 {
-+					port = <3>;
-+				};
-+
-+				port@4 {
-+					port = <4>;
-+				};
-+
-+				port@5 {
-+					port = <5>;
-+				};
-+
-+				port@6 {
-+					port = <6>;
-+				};
-+
-+				port@7 {
-+					port = <7>;
-+				};
-+
-+				port@8 {
-+					port = <8>;
-+				};
-+
-+				port@9 {
-+					port = <9>;
-+				};
-+
-+				port@10 {
-+					port = <10>;
-+				};
-+
-+				port@11 {
-+					port = <11>;
-+				};
-+
-+				port@12 {
-+					port = <12>;
-+				};
-+
-+				port@13 {
-+					port = <13>;
-+				};
-+
-+				port@14 {
-+					port = <14>;
-+				};
-+			};
-+
-+			sbefifo@2400 {
-+				compatible = "ibm,p9-sbefifo";
-+				reg = <0x2400 0x400>;
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+
-+				occ@1 {
-+					compatible = "ibm,p9-occ";
-+					reg = <1>;
-+				};
-+			};
-+
-+			hub@3400 {
-+				compatible = "fsi-master-hub";
-+				reg = <0x3400 0x400>;
-+				#address-cells = <2>;
-+				#size-cells = <0>;
-+
-+				cfam@1,0 {
-+					reg = <1 0>;
-+					#address-cells = <1>;
-+					#size-cells = <1>;
-+
-+					i2c-master@1800 {
-+						compatible =
-+							"ibm,fsi-i2c-master";
-+						reg = <0x1800 0x400>;
-+						#address-cells = <1>;
-+						#size-cells = <0>;
-+
-+						port@0 {
-+							port = <0>;
-+						};
-+
-+						port@1 {
-+							port = <1>;
-+						};
-+
-+						port@2 {
-+							port = <2>;
-+						};
-+
-+						port@3 {
-+							port = <3>;
-+						};
-+
-+						port@4 {
-+							port = <4>;
-+						};
-+
-+						port@5 {
-+							port = <5>;
-+						};
-+
-+						port@6 {
-+							port = <6>;
-+						};
-+
-+						port@7 {
-+							port = <7>;
-+						};
-+
-+						port@8 {
-+							port = <8>;
-+						};
-+
-+						port@9 {
-+							port = <9>;
-+						};
-+
-+						port@10 {
-+							port = <10>;
-+						};
-+
-+						port@11 {
-+							port = <11>;
-+						};
-+
-+						port@12 {
-+							port = <12>;
-+						};
-+
-+						port@13 {
-+							port = <13>;
-+						};
-+
-+						port@14 {
-+							port = <14>;
-+						};
-+					};
-+
-+					sbefifo@2400 {
-+						compatible = "ibm,p9-sbefifo";
-+						reg = <0x2400 0x400>;
-+						#address-cells = <1>;
-+						#size-cells = <0>;
-+
-+						occ@2 {
-+							compatible =
-+								"ibm,p9-occ";
-+							reg = <2>;
-+						};
-+					};
-+				};
-+			};
-+		};
- 	};
- 
- 	iio-hwmon {
-diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts b/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
-index b5c4c0f..6f36e56 100644
---- a/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
-+++ b/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
-@@ -77,6 +77,8 @@
- 
- 	gpio-fsi {
- 		compatible = "fsi-master-gpio", "fsi-master";
-+		#address-cells = <2>;
-+		#size-cells = <0>;
- 
- 		status = "okay";
- 
-@@ -85,6 +87,185 @@
- 		trans-gpios = <&gpio ASPEED_GPIO(O, 6) GPIO_ACTIVE_HIGH>;
- 		enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
- 		mux-gpios = <&gpio ASPEED_GPIO(P, 6) GPIO_ACTIVE_HIGH>;
-+
-+		cfam@0,0 {
-+			reg = <0 0>;
-+			#address-cells = <1>;
-+			#size-cells = <1>;
-+
-+			i2c-master@1800 {
-+				compatible = "ibm,fsi-i2c-master";
-+				reg = <0x1800 0x400>;
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+
-+				port@0 {
-+					port = <0>;
-+				};
-+
-+				port@1 {
-+					port = <1>;
-+				};
-+
-+				port@2 {
-+					port = <2>;
-+				};
-+
-+				port@3 {
-+					port = <3>;
-+				};
-+
-+				port@4 {
-+					port = <4>;
-+				};
-+
-+				port@5 {
-+					port = <5>;
-+				};
-+
-+				port@6 {
-+					port = <6>;
-+				};
-+
-+				port@7 {
-+					port = <7>;
-+				};
-+
-+				port@8 {
-+					port = <8>;
-+				};
-+
-+				port@9 {
-+					port = <9>;
-+				};
-+
-+				port@10 {
-+					port = <10>;
-+				};
-+
-+				port@11 {
-+					port = <11>;
-+				};
-+
-+				port@12 {
-+					port = <12>;
-+				};
-+
-+				port@13 {
-+					port = <13>;
-+				};
-+
-+				port@14 {
-+					port = <14>;
-+				};
-+			};
-+
-+			sbefifo@2400 {
-+				compatible = "ibm,p9-sbefifo";
-+				reg = <0x2400 0x400>;
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+
-+				occ@1 {
-+					compatible = "ibm,p9-occ";
-+					reg = <1>;
-+				};
-+			};
-+
-+			hub@3400 {
-+				compatible = "fsi-master-hub";
-+				reg = <0x3400 0x400>;
-+				#address-cells = <2>;
-+				#size-cells = <0>;
-+
-+				cfam@1,0 {
-+					reg = <1 0>;
-+					#address-cells = <1>;
-+					#size-cells = <1>;
-+
-+					i2c-master@1800 {
-+						compatible =
-+							"ibm,fsi-i2c-master";
-+						reg = <0x1800 0x400>;
-+						#address-cells = <1>;
-+						#size-cells = <0>;
-+
-+						port@0 {
-+							port = <0>;
-+						};
-+
-+						port@1 {
-+							port = <1>;
-+						};
-+
-+						port@2 {
-+							port = <2>;
-+						};
-+
-+						port@3 {
-+							port = <3>;
-+						};
-+
-+						port@4 {
-+							port = <4>;
-+						};
-+
-+						port@5 {
-+							port = <5>;
-+						};
-+
-+						port@6 {
-+							port = <6>;
-+						};
-+
-+						port@7 {
-+							port = <7>;
-+						};
-+
-+						port@8 {
-+							port = <8>;
-+						};
-+
-+						port@9 {
-+							port = <9>;
-+						};
-+
-+						port@10 {
-+							port = <10>;
-+						};
-+
-+						port@11 {
-+							port = <11>;
-+						};
-+
-+						port@12 {
-+							port = <12>;
-+						};
-+
-+						port@13 {
-+							port = <13>;
-+						};
-+
-+						port@14 {
-+							port = <14>;
-+						};
-+					};
-+
-+					sbefifo@2400 {
-+						compatible = "ibm,p9-sbefifo";
-+						reg = <0x2400 0x400>;
-+						#address-cells = <1>;
-+						#size-cells = <0>;
-+
-+						occ@2 {
-+							compatible =
-+								"ibm,p9-occ";
-+							reg = <2>;
-+						};
-+					};
-+				};
-+			};
-+		};
- 	};
- 
- 	iio-hwmon {
--- 
-1.8.3.1
-
diff --git a/common/recipes-kernel/linux/linux-obmc/0001-fsi-Match-fsi-slaves-engines-to-available-device-tre.patch b/common/recipes-kernel/linux/linux-obmc/0001-fsi-Match-fsi-slaves-engines-to-available-device-tre.patch
deleted file mode 100644
index 6fdfe93..0000000
--- a/common/recipes-kernel/linux/linux-obmc/0001-fsi-Match-fsi-slaves-engines-to-available-device-tre.patch
+++ /dev/null
@@ -1,236 +0,0 @@
-From 8f10daa0cc99ce286b9a2f249f1fa0a245d4fc03 Mon Sep 17 00:00:00 2001
-From: "Edward A. James" <eajames@us.ibm.com>
-Date: Wed, 17 May 2017 09:46:19 -0500
-Subject: [PATCH] fsi: Match fsi slaves & engines to available device tree
- nodes
-
-This change populates device tree nodes for scanned FSI slaves and
-engines. If the master populates ->of_node of the FSI master device,
-we'll look for matching slaves, and under those slaves we'll look for
-matching engines.
-
-This means that FSI drivers will have their ->of_node pointer populated
-if there's a corresponding DT node, which they can use for further
-device discover.
-
-Presence of device tree nodes is optional, and only required for
-fsi device drivers that need extra properties, or subordinate devices,
-to be enumerated.
-
-Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/fsi/fsi-core.c        | 99 +++++++++++++++++++++++++++++++++++++++++++
- drivers/fsi/fsi-master-gpio.c |  4 ++
- drivers/fsi/fsi-master-hub.c  |  4 ++
- 3 files changed, 107 insertions(+)
-
-diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
-index 7ca5b74..71e3af9 100644
---- a/drivers/fsi/fsi-core.c
-+++ b/drivers/fsi/fsi-core.c
-@@ -17,6 +17,7 @@
- #include <linux/fsi.h>
- #include <linux/idr.h>
- #include <linux/module.h>
-+#include <linux/of.h>
- #include <linux/slab.h>
- 
- #include "fsi-master.h"
-@@ -125,6 +126,7 @@ static void fsi_device_release(struct device *_device)
- {
- 	struct fsi_device *device = to_fsi_dev(_device);
- 
-+	of_node_put(device->dev.of_node);
- 	kfree(device);
- }
- 
-@@ -337,6 +339,57 @@ extern void fsi_slave_release_range(struct fsi_slave *slave,
- {
- }
- 
-+static bool fsi_device_node_matches(struct device *dev, struct device_node *np,
-+		uint32_t addr, uint32_t size)
-+{
-+	unsigned int len, na, ns;
-+	const __be32 *prop;
-+	uint32_t psize;
-+
-+	na = of_n_addr_cells(np);
-+	ns = of_n_size_cells(np);
-+
-+	if (na != 1 || ns != 1)
-+		return false;
-+
-+	prop = of_get_property(np, "reg", &len);
-+	if (!prop || len != 8)
-+		return false;
-+
-+	if (of_read_number(prop, 1) != addr)
-+		return false;
-+
-+	psize = of_read_number(prop + 1, 1);
-+	if (psize != size) {
-+		dev_warn(dev,
-+			"node %s matches probed address, but not size (got 0x%x, expected 0x%x)",
-+			of_node_full_name(np), psize, size);
-+	}
-+
-+	return true;
-+}
-+
-+/* Find a matching node for the slave engine at @address, using @size bytes
-+ * of space. Returns NULL if not found, or a matching node with refcount
-+ * already incremented.
-+ */
-+static struct device_node *fsi_device_find_of_node(struct fsi_device *dev)
-+{
-+	struct device_node *parent, *np;
-+
-+	parent = dev_of_node(&dev->slave->dev);
-+	if (!parent)
-+		return NULL;
-+
-+	for_each_child_of_node(parent, np) {
-+		if (fsi_device_node_matches(&dev->dev, np,
-+					dev->addr, dev->size))
-+			return np;
-+	}
-+
-+	return NULL;
-+}
-+
- static int fsi_slave_scan(struct fsi_slave *slave)
- {
- 	uint32_t engine_addr;
-@@ -405,6 +458,7 @@ static int fsi_slave_scan(struct fsi_slave *slave)
- 			dev_set_name(&dev->dev, "%02x:%02x:%02x:%02x",
- 					slave->master->idx, slave->link,
- 					slave->id, i - 2);
-+			dev->dev.of_node = fsi_device_find_of_node(dev);
- 
- 			rc = device_register(&dev->dev);
- 			if (rc) {
-@@ -561,9 +615,53 @@ static void fsi_slave_release(struct device *dev)
- {
- 	struct fsi_slave *slave = to_fsi_slave(dev);
- 
-+	of_node_put(dev->of_node);
- 	kfree(slave);
- }
- 
-+static bool fsi_slave_node_matches(struct device_node *np,
-+		int link, uint8_t id)
-+{
-+	unsigned int len, na, ns;
-+	const __be32 *prop;
-+
-+	na = of_n_addr_cells(np);
-+	ns = of_n_size_cells(np);
-+
-+	/* Ensure we have the correct format for addresses and sizes in
-+	 * reg properties
-+	 */
-+	if (na != 2 || ns != 0)
-+		return false;
-+
-+	prop = of_get_property(np, "reg", &len);
-+	if (!prop || len != 8)
-+		return false;
-+
-+	return (of_read_number(prop, 1) == link) &&
-+		(of_read_number(prop + 1, 1) == id);
-+}
-+
-+/* Find a matching node for the slave at (link, id). Returns NULL if none
-+ * found, or a matching node with refcount already incremented.
-+ */
-+static struct device_node *fsi_slave_find_of_node(struct fsi_master *master,
-+		int link, uint8_t id)
-+{
-+	struct device_node *parent, *np;
-+
-+	parent = dev_of_node(&master->dev);
-+	if (!parent)
-+		return NULL;
-+
-+	for_each_child_of_node(parent, np) {
-+		if (fsi_slave_node_matches(np, link, id))
-+			return np;
-+	}
-+
-+	return NULL;
-+}
-+
- static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
- {
- 	uint32_t chip_id, llmode;
-@@ -626,6 +724,7 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
- 
- 	slave->master = master;
- 	slave->dev.parent = &master->dev;
-+	slave->dev.of_node = fsi_slave_find_of_node(master, link, id);
- 	slave->dev.release = fsi_slave_release;
- 	slave->link = link;
- 	slave->id = id;
-diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
-index ef209ef..2a6a812 100644
---- a/drivers/fsi/fsi-master-gpio.c
-+++ b/drivers/fsi/fsi-master-gpio.c
-@@ -5,6 +5,7 @@
- #include <linux/platform_device.h>
- #include <linux/gpio/consumer.h>
- #include <linux/module.h>
-+#include <linux/of.h>
- #include <linux/delay.h>
- #include <linux/fsi.h>
- #include <linux/device.h>
-@@ -529,6 +530,7 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
- 
- 	master->dev = &pdev->dev;
- 	master->master.dev.parent = master->dev;
-+	master->master.dev.of_node = of_node_get(dev_of_node(master->dev));
- 	master->master.dev.release = fsi_master_gpio_release;
- 
- 	gpio = devm_gpiod_get(&pdev->dev, "clock", 0);
-@@ -598,6 +600,8 @@ static int fsi_master_gpio_remove(struct platform_device *pdev)
- 		devm_gpiod_put(&pdev->dev, master->gpio_mux);
- 	fsi_master_unregister(&master->master);
- 
-+	of_node_put(master->master.dev.of_node);
-+
- 	return 0;
- }
- 
-diff --git a/drivers/fsi/fsi-master-hub.c b/drivers/fsi/fsi-master-hub.c
-index 133b9bf..3223a67 100644
---- a/drivers/fsi/fsi-master-hub.c
-+++ b/drivers/fsi/fsi-master-hub.c
-@@ -16,6 +16,7 @@
- #include <linux/delay.h>
- #include <linux/fsi.h>
- #include <linux/module.h>
-+#include <linux/of.h>
- #include <linux/slab.h>
- 
- #include "fsi-master.h"
-@@ -274,6 +275,7 @@ static int hub_master_probe(struct device *dev)
- 
- 	hub->master.dev.parent = dev;
- 	hub->master.dev.release = hub_master_release;
-+	hub->master.dev.of_node = of_node_get(dev_of_node(dev));
- 
- 	hub->master.n_links = links;
- 	hub->master.read = hub_master_read;
-@@ -302,6 +304,8 @@ static int hub_master_remove(struct device *dev)
- 
- 	fsi_master_unregister(&hub->master);
- 	fsi_slave_release_range(hub->upstream->slave, hub->addr, hub->size);
-+	of_node_put(hub->master.dev.of_node);
-+
- 	return 0;
- }
- 
--- 
-1.8.3.1
-
diff --git a/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch b/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch
deleted file mode 100644
index 8ade1be..0000000
--- a/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch
+++ /dev/null
@@ -1,821 +0,0 @@
-From b3991e27b26930ef46206dad17715d8ac2f38a4e Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <tpearson@raptorengineering.com>
-Date: Tue, 11 Oct 2016 09:35:51 -0500
-Subject: [PATCH] hwmon: Add support for MAX31785 intelligent fan controller
-
-Add a basic driver for the MAX31785, focusing on the fan control
-features but ignoring the temperature and voltage monitoring
-features of the device.
-
-This driver supports all fan control modes and tachometer / PWM
-readback where applicable.
-
-Signed-off-by: Timothy Pearson <tpearson@raptorengineering.com>
-Signed-off-by: Joel Stanley <joel@jms.id.au>
----
- Documentation/hwmon/max31785 |  36 +++
- drivers/hwmon/Kconfig        |  10 +
- drivers/hwmon/Makefile       |   1 +
- drivers/hwmon/max31785.c     | 714 +++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 761 insertions(+)
- create mode 100644 Documentation/hwmon/max31785
- create mode 100644 drivers/hwmon/max31785.c
-
-diff --git a/Documentation/hwmon/max31785 b/Documentation/hwmon/max31785
-new file mode 100644
-index 0000000..0911d20
---- /dev/null
-+++ b/Documentation/hwmon/max31785
-@@ -0,0 +1,36 @@
-+Kernel driver max31785
-+======================
-+
-+Supported chips:
-+  * Maxim MAX31785
-+    Prefix: 'max31785'
-+    Addresses scanned: 0x52 0x53 0x54 0x55
-+    Datasheet: http://pdfserv.maximintegrated.com/en/ds/MAX31785.pdf
-+
-+Author: Timothy Pearson <tpearson@raptorengineering.com>
-+
-+
-+Description
-+-----------
-+
-+This driver implements support for the Maxim MAX31785 chip.
-+
-+The MAX31785 controls the speeds of up to six fans using six independent
-+PWM outputs. The desired fan speeds (or PWM duty cycles) are written
-+through the I2C interface. The outputs drive "4-wire" fans directly,
-+or can be used to modulate the fan's power terminals using an external
-+pass transistor.
-+
-+Tachometer inputs monitor fan tachometer logic outputs for precise (+/-1%)
-+monitoring and control of fan RPM as well as detection of fan failure.
-+
-+
-+Sysfs entries
-+-------------
-+
-+fan[1-6]_input           RO  fan tachometer speed in RPM
-+fan[1-6]_fault           RO  fan experienced fault
-+fan[1-6]_pulses          RW  tachometer pulses per fan revolution
-+fan[1-6]_target          RW  desired fan speed in RPM
-+pwm[1-6]_enable          RW  pwm mode, 0=disabled, 1=pwm, 2=rpm, 3=automatic
-+pwm[1-6]                 RW  fan target duty cycle (0-255)
-diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
-index 190d270..136605d 100644
---- a/drivers/hwmon/Kconfig
-+++ b/drivers/hwmon/Kconfig
-@@ -886,6 +886,16 @@ config SENSORS_MAX6697
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called max6697.
- 
-+config SENSORS_MAX31785
-+	tristate "Maxim MAX31785 sensor chip"
-+	depends on I2C
-+	help
-+	  If you say yes here you get support for 6-Channel PWM-Output
-+	  Fan RPM Controller.
-+
-+	  This driver can also be built as a module.  If so, the module
-+	  will be called max31785.
-+
- config SENSORS_MAX31790
- 	tristate "Maxim MAX31790 sensor chip"
- 	depends on I2C
-diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
-index d2cb7e8..e8ba5c6 100644
---- a/drivers/hwmon/Makefile
-+++ b/drivers/hwmon/Makefile
-@@ -119,6 +119,7 @@ obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
- obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
- obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
- obj-$(CONFIG_SENSORS_MAX6697)	+= max6697.o
-+obj-$(CONFIG_SENSORS_MAX31785)	+= max31785.o
- obj-$(CONFIG_SENSORS_MAX31790)	+= max31790.o
- obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
- obj-$(CONFIG_SENSORS_MCP3021)	+= mcp3021.o
-diff --git a/drivers/hwmon/max31785.c b/drivers/hwmon/max31785.c
-new file mode 100644
-index 0000000..fb7b3f0
---- /dev/null
-+++ b/drivers/hwmon/max31785.c
-@@ -0,0 +1,714 @@
-+/*
-+ * max31785.c - Part of lm_sensors, Linux kernel modules for hardware
-+ *             monitoring.
-+ *
-+ * (C) 2016 Raptor Engineering, LLC
-+ *
-+ * 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/err.h>
-+#include <linux/hwmon.h>
-+#include <linux/hwmon-sysfs.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/jiffies.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+
-+/* MAX31785 device IDs */
-+#define MAX31785_MFR_ID				0x4d
-+#define MAX31785_MFR_MODEL			0x53
-+
-+/* MAX31785 registers */
-+#define MAX31785_REG_PAGE			0x00
-+#define MAX31785_PAGE_FAN_CONFIG(ch)		(0x00 + (ch))
-+#define MAX31785_REG_FAN_CONFIG_1_2		0x3a
-+#define MAX31785_REG_FAN_COMMAND_1		0x3b
-+#define MAX31785_REG_STATUS_FANS_1_2		0x81
-+#define MAX31785_REG_FAN_SPEED_1		0x90
-+#define MAX31785_REG_MFR_ID			0x99
-+#define MAX31785_REG_MFR_MODEL			0x9a
-+#define MAX31785_REG_MFR_FAN_CONFIG		0xf1
-+#define MAX31785_REG_READ_FAN_PWM		0xf3
-+
-+/* Fan Config register bits */
-+#define MAX31785_FAN_CFG_PWM_ENABLE		0x80
-+#define MAX31785_FAN_CFG_CONTROL_MODE_RPM	0x40
-+#define MAX31785_FAN_CFG_PULSE_MASK		0x30
-+#define MAX31785_FAN_CFG_PULSE_SHIFT		4
-+#define MAX31785_FAN_CFG_PULSE_OFFSET		1
-+
-+/* Fan Status register bits */
-+#define MAX31785_FAN_STATUS_FAULT_MASK		0x80
-+
-+/* Fan Command constants */
-+#define MAX31785_FAN_COMMAND_PWM_RATIO		40
-+
-+#define NR_CHANNEL				6
-+
-+/* Addresses to scan */
-+static const unsigned short normal_i2c[] = { 0x52, 0x53, 0x54, 0x55,
-+							I2C_CLIENT_END };
-+
-+/*
-+ * Client data (each client gets its own)
-+ */
-+struct max31785_data {
-+	struct i2c_client *client;
-+	struct mutex device_lock;
-+	bool valid; /* zero until following fields are valid */
-+	unsigned long last_updated; /* in jiffies */
-+
-+	/* register values */
-+	u8 fan_config[NR_CHANNEL];
-+	u16 fan_command[NR_CHANNEL];
-+	u8 mfr_fan_config[NR_CHANNEL];
-+	u8 fault_status[NR_CHANNEL];
-+	u16 tach_rpm[NR_CHANNEL];
-+	u16 pwm[NR_CHANNEL];
-+};
-+
-+static int max31785_set_page(struct i2c_client *client,
-+				u8 page)
-+{
-+	return i2c_smbus_write_byte_data(client,
-+			MAX31785_REG_PAGE,
-+			page);
-+}
-+
-+static int max31785_read_fan_data(struct i2c_client *client,
-+				u8 fan, u8 reg, u8 byte_mode)
-+{
-+	int rv;
-+
-+	rv = max31785_set_page(client, MAX31785_PAGE_FAN_CONFIG(fan));
-+	if (rv < 0)
-+		return rv;
-+
-+	if (byte_mode)
-+		rv = i2c_smbus_read_byte_data(client, reg);
-+	else
-+		rv = i2c_smbus_read_word_data(client, reg);
-+
-+	return rv;
-+}
-+
-+static int max31785_write_fan_data(struct i2c_client *client,
-+				u8 fan, u8 reg, u16 data,
-+				u8 byte_mode)
-+{
-+	int err;
-+
-+	err = max31785_set_page(client, MAX31785_PAGE_FAN_CONFIG(fan));
-+	if (err < 0)
-+		return err;
-+
-+	if (byte_mode)
-+		err = i2c_smbus_write_byte_data(client, reg, data);
-+	else
-+		err = i2c_smbus_write_word_data(client, reg, data);
-+
-+	if (err < 0)
-+		return err;
-+
-+	return 0;
-+}
-+
-+static bool is_automatic_control_mode(struct max31785_data *data,
-+			int index)
-+{
-+	if (data->fan_command[index] > 0x7fff)
-+		return true;
-+	else
-+		return false;
-+}
-+
-+static struct max31785_data *max31785_update_device(struct device *dev)
-+{
-+	struct max31785_data *data = dev_get_drvdata(dev);
-+	struct i2c_client *client = data->client;
-+	struct max31785_data *ret = data;
-+	int i;
-+	int rv;
-+
-+	mutex_lock(&data->device_lock);
-+
-+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-+		for (i = 0; i < NR_CHANNEL; i++) {
-+			rv = max31785_read_fan_data(client, i,
-+					MAX31785_REG_STATUS_FANS_1_2, 1);
-+			if (rv < 0)
-+				goto abort;
-+			data->fault_status[i] = rv;
-+
-+			rv = max31785_read_fan_data(client, i,
-+					MAX31785_REG_FAN_SPEED_1, 0);
-+			if (rv < 0)
-+				goto abort;
-+			data->tach_rpm[i] = rv;
-+
-+			if ((data->fan_config[i]
-+				& MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+				|| is_automatic_control_mode(data, i)) {
-+				rv = max31785_read_fan_data(client, i,
-+						MAX31785_REG_READ_FAN_PWM, 0);
-+				if (rv < 0)
-+					goto abort;
-+				data->pwm[i] = rv;
-+			}
-+
-+			if (!is_automatic_control_mode(data, i)) {
-+				/* Poke watchdog for manual fan control */
-+				rv = max31785_write_fan_data(client,
-+					i, MAX31785_REG_FAN_COMMAND_1,
-+					data->fan_command[i], 0);
-+				if (rv < 0)
-+					goto abort;
-+			}
-+		}
-+
-+		data->last_updated = jiffies;
-+		data->valid = true;
-+	}
-+	goto done;
-+
-+abort:
-+	data->valid = false;
-+	ret = ERR_PTR(rv);
-+
-+done:
-+	mutex_unlock(&data->device_lock);
-+
-+	return ret;
-+}
-+
-+static ssize_t get_fan(struct device *dev,
-+		       struct device_attribute *devattr, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = max31785_update_device(dev);
-+
-+	if (IS_ERR(data))
-+		return PTR_ERR(data);
-+
-+	return sprintf(buf, "%d\n", data->tach_rpm[attr->index]);
-+}
-+
-+static ssize_t get_fan_target(struct device *dev,
-+			      struct device_attribute *devattr, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = max31785_update_device(dev);
-+	int rpm;
-+
-+	if (IS_ERR(data))
-+		return PTR_ERR(data);
-+
-+	if (data->fan_config[attr->index]
-+		& MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+		rpm = data->fan_command[attr->index];
-+	else
-+		rpm = data->fan_command[attr->index]
-+					/ MAX31785_FAN_COMMAND_PWM_RATIO;
-+
-+	return sprintf(buf, "%d\n", rpm);
-+}
-+
-+static ssize_t set_fan_target(struct device *dev,
-+			      struct device_attribute *devattr,
-+			      const char *buf, size_t count)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = dev_get_drvdata(dev);
-+	struct i2c_client *client = data->client;
-+	unsigned long rpm;
-+	int err;
-+
-+	err = kstrtoul(buf, 10, &rpm);
-+	if (err)
-+		return err;
-+
-+	if (rpm > 0x7fff)
-+		return -EINVAL;
-+
-+	mutex_lock(&data->device_lock);
-+
-+	/* Write new RPM value */
-+	data->fan_command[attr->index] = rpm;
-+	err = max31785_write_fan_data(client, attr->index,
-+				MAX31785_REG_FAN_COMMAND_1,
-+				data->fan_command[attr->index], 0);
-+
-+	mutex_unlock(&data->device_lock);
-+
-+	if (err < 0)
-+		return err;
-+
-+	return count;
-+}
-+
-+static ssize_t get_fan_pulses(struct device *dev,
-+			      struct device_attribute *devattr, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = max31785_update_device(dev);
-+	int pulses;
-+
-+	if (IS_ERR(data))
-+		return PTR_ERR(data);
-+
-+	pulses = ((data->fan_config[attr->index] & MAX31785_FAN_CFG_PULSE_MASK)
-+			>> MAX31785_FAN_CFG_PULSE_SHIFT)
-+			+ MAX31785_FAN_CFG_PULSE_OFFSET;
-+
-+	return sprintf(buf, "%d\n", pulses);
-+}
-+
-+static ssize_t set_fan_pulses(struct device *dev,
-+			      struct device_attribute *devattr,
-+			      const char *buf, size_t count)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = dev_get_drvdata(dev);
-+	struct i2c_client *client = data->client;
-+	unsigned long pulses;
-+	int err;
-+
-+	err = kstrtoul(buf, 10, &pulses);
-+	if (err)
-+		return err;
-+
-+	if (pulses > 4)
-+		return -EINVAL;
-+
-+	data->fan_config[attr->index] &= MAX31785_FAN_CFG_PULSE_MASK;
-+	data->fan_config[attr->index] |=
-+				((pulses - MAX31785_FAN_CFG_PULSE_OFFSET)
-+				<< MAX31785_FAN_CFG_PULSE_SHIFT);
-+
-+	mutex_lock(&data->device_lock);
-+
-+	/* Write new pulse value */
-+	data->fan_command[attr->index] = pulses;
-+	err = max31785_write_fan_data(client, attr->index,
-+				MAX31785_REG_FAN_CONFIG_1_2,
-+				data->fan_config[attr->index], 1);
-+
-+	mutex_unlock(&data->device_lock);
-+
-+	if (err < 0)
-+		return err;
-+
-+	return count;
-+}
-+
-+static ssize_t get_pwm(struct device *dev,
-+		       struct device_attribute *devattr, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = max31785_update_device(dev);
-+	int pwm;
-+
-+	if (IS_ERR(data))
-+		return PTR_ERR(data);
-+
-+	if ((data->fan_config[attr->index]
-+		& MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+		|| is_automatic_control_mode(data, attr->index))
-+		pwm = data->pwm[attr->index] / 100;
-+	else
-+		pwm = data->fan_command[attr->index]
-+					/ MAX31785_FAN_COMMAND_PWM_RATIO;
-+
-+	return sprintf(buf, "%d\n", pwm);
-+}
-+
-+static ssize_t set_pwm(struct device *dev,
-+		       struct device_attribute *devattr,
-+		       const char *buf, size_t count)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = dev_get_drvdata(dev);
-+	struct i2c_client *client = data->client;
-+	unsigned long pwm;
-+	int err;
-+
-+	err = kstrtoul(buf, 10, &pwm);
-+	if (err)
-+		return err;
-+
-+	if (pwm > 255)
-+		return -EINVAL;
-+
-+	mutex_lock(&data->device_lock);
-+
-+	/* Write new PWM value */
-+	data->fan_command[attr->index] = pwm * MAX31785_FAN_COMMAND_PWM_RATIO;
-+	err = max31785_write_fan_data(client, attr->index,
-+				MAX31785_REG_FAN_COMMAND_1,
-+				data->fan_command[attr->index], 0);
-+
-+	mutex_unlock(&data->device_lock);
-+
-+	if (err < 0)
-+		return err;
-+
-+	return count;
-+}
-+
-+static ssize_t get_pwm_enable(struct device *dev,
-+			      struct device_attribute *devattr, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = max31785_update_device(dev);
-+	int mode;
-+
-+	if (IS_ERR(data))
-+		return PTR_ERR(data);
-+
-+	if (!(data->fan_config[attr->index] & MAX31785_FAN_CFG_PWM_ENABLE))
-+		mode = 0;
-+	else if (is_automatic_control_mode(data, attr->index))
-+		mode = 3;
-+	else if (data->fan_config[attr->index]
-+		& MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+		mode = 2;
-+	else
-+		mode = 1;
-+
-+	return sprintf(buf, "%d\n", mode);
-+}
-+
-+static ssize_t set_pwm_enable(struct device *dev,
-+			      struct device_attribute *devattr,
-+			      const char *buf, size_t count)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = dev_get_drvdata(dev);
-+	struct i2c_client *client = data->client;
-+	unsigned long mode;
-+	int err;
-+
-+	err = kstrtoul(buf, 10, &mode);
-+	if (err)
-+		return err;
-+
-+	switch (mode) {
-+	case 0:
-+		data->fan_config[attr->index] =
-+			data->fan_config[attr->index]
-+			& ~MAX31785_FAN_CFG_PWM_ENABLE;
-+		break;
-+	case 1:
-+	case 2:
-+	case 3:
-+		data->fan_config[attr->index] =
-+			data->fan_config[attr->index]
-+			 | MAX31785_FAN_CFG_PWM_ENABLE;
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	switch (mode) {
-+	case 0:
-+		break;
-+	case 1:
-+		data->fan_config[attr->index] =
-+			data->fan_config[attr->index]
-+			& ~MAX31785_FAN_CFG_CONTROL_MODE_RPM;
-+		break;
-+	case 2:
-+		data->fan_config[attr->index] =
-+			data->fan_config[attr->index]
-+			| MAX31785_FAN_CFG_CONTROL_MODE_RPM;
-+		break;
-+	case 3:
-+		data->fan_command[attr->index] = 0xffff;
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	mutex_lock(&data->device_lock);
-+
-+	err = max31785_write_fan_data(client, attr->index,
-+				MAX31785_REG_FAN_CONFIG_1_2,
-+				data->fan_config[attr->index], 1);
-+
-+	if (err < 0)
-+		goto abort;
-+
-+	err = max31785_write_fan_data(client, attr->index,
-+				MAX31785_REG_FAN_COMMAND_1,
-+				data->fan_command[attr->index], 0);
-+
-+abort:
-+	mutex_unlock(&data->device_lock);
-+
-+	if (err < 0)
-+		return err;
-+
-+	return count;
-+}
-+
-+static ssize_t get_fan_fault(struct device *dev,
-+			     struct device_attribute *devattr, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+	struct max31785_data *data = max31785_update_device(dev);
-+	int fault;
-+
-+	if (IS_ERR(data))
-+		return PTR_ERR(data);
-+
-+	fault = !!(data->fault_status[attr->index]
-+			& MAX31785_FAN_STATUS_FAULT_MASK);
-+
-+	return sprintf(buf, "%d\n", fault);
-+}
-+
-+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0);
-+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1);
-+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2);
-+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3);
-+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, get_fan, NULL, 4);
-+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, get_fan, NULL, 5);
-+
-+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan_fault, NULL, 0);
-+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, get_fan_fault, NULL, 1);
-+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, get_fan_fault, NULL, 2);
-+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, get_fan_fault, NULL, 3);
-+static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, get_fan_fault, NULL, 4);
-+static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, get_fan_fault, NULL, 5);
-+
-+static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO,
-+		get_fan_target, set_fan_target, 0);
-+static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO,
-+		get_fan_target, set_fan_target, 1);
-+static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO,
-+		get_fan_target, set_fan_target, 2);
-+static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO,
-+		get_fan_target, set_fan_target, 3);
-+static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO,
-+		get_fan_target, set_fan_target, 4);
-+static SENSOR_DEVICE_ATTR(fan6_target, S_IWUSR | S_IRUGO,
-+		get_fan_target, set_fan_target, 5);
-+
-+static SENSOR_DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO,
-+		get_fan_pulses, set_fan_pulses, 0);
-+static SENSOR_DEVICE_ATTR(fan2_pulses, S_IWUSR | S_IRUGO,
-+		get_fan_pulses, set_fan_pulses, 1);
-+static SENSOR_DEVICE_ATTR(fan3_pulses, S_IWUSR | S_IRUGO,
-+		get_fan_pulses, set_fan_pulses, 2);
-+static SENSOR_DEVICE_ATTR(fan4_pulses, S_IWUSR | S_IRUGO,
-+		get_fan_pulses, set_fan_pulses, 3);
-+static SENSOR_DEVICE_ATTR(fan5_pulses, S_IWUSR | S_IRUGO,
-+		get_fan_pulses, set_fan_pulses, 4);
-+static SENSOR_DEVICE_ATTR(fan6_pulses, S_IWUSR | S_IRUGO,
-+		get_fan_pulses, set_fan_pulses, 5);
-+
-+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 0);
-+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 1);
-+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 2);
-+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 3);
-+static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 4);
-+static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 5);
-+
-+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
-+		get_pwm_enable, set_pwm_enable, 0);
-+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
-+		get_pwm_enable, set_pwm_enable, 1);
-+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
-+		get_pwm_enable, set_pwm_enable, 2);
-+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO,
-+		get_pwm_enable, set_pwm_enable, 3);
-+static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO,
-+		get_pwm_enable, set_pwm_enable, 4);
-+static SENSOR_DEVICE_ATTR(pwm6_enable, S_IWUSR | S_IRUGO,
-+		get_pwm_enable, set_pwm_enable, 5);
-+
-+static struct attribute *max31785_attrs[] = {
-+	&sensor_dev_attr_fan1_input.dev_attr.attr,
-+	&sensor_dev_attr_fan2_input.dev_attr.attr,
-+	&sensor_dev_attr_fan3_input.dev_attr.attr,
-+	&sensor_dev_attr_fan4_input.dev_attr.attr,
-+	&sensor_dev_attr_fan5_input.dev_attr.attr,
-+	&sensor_dev_attr_fan6_input.dev_attr.attr,
-+
-+	&sensor_dev_attr_fan1_fault.dev_attr.attr,
-+	&sensor_dev_attr_fan2_fault.dev_attr.attr,
-+	&sensor_dev_attr_fan3_fault.dev_attr.attr,
-+	&sensor_dev_attr_fan4_fault.dev_attr.attr,
-+	&sensor_dev_attr_fan5_fault.dev_attr.attr,
-+	&sensor_dev_attr_fan6_fault.dev_attr.attr,
-+
-+	&sensor_dev_attr_fan1_target.dev_attr.attr,
-+	&sensor_dev_attr_fan2_target.dev_attr.attr,
-+	&sensor_dev_attr_fan3_target.dev_attr.attr,
-+	&sensor_dev_attr_fan4_target.dev_attr.attr,
-+	&sensor_dev_attr_fan5_target.dev_attr.attr,
-+	&sensor_dev_attr_fan6_target.dev_attr.attr,
-+
-+	&sensor_dev_attr_fan1_pulses.dev_attr.attr,
-+	&sensor_dev_attr_fan2_pulses.dev_attr.attr,
-+	&sensor_dev_attr_fan3_pulses.dev_attr.attr,
-+	&sensor_dev_attr_fan4_pulses.dev_attr.attr,
-+	&sensor_dev_attr_fan5_pulses.dev_attr.attr,
-+	&sensor_dev_attr_fan6_pulses.dev_attr.attr,
-+
-+	&sensor_dev_attr_pwm1.dev_attr.attr,
-+	&sensor_dev_attr_pwm2.dev_attr.attr,
-+	&sensor_dev_attr_pwm3.dev_attr.attr,
-+	&sensor_dev_attr_pwm4.dev_attr.attr,
-+	&sensor_dev_attr_pwm5.dev_attr.attr,
-+	&sensor_dev_attr_pwm6.dev_attr.attr,
-+
-+	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
-+	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
-+	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
-+	&sensor_dev_attr_pwm4_enable.dev_attr.attr,
-+	&sensor_dev_attr_pwm5_enable.dev_attr.attr,
-+	&sensor_dev_attr_pwm6_enable.dev_attr.attr,
-+	NULL
-+};
-+
-+static umode_t max31785_attrs_visible(struct kobject *kobj,
-+				     struct attribute *a, int n)
-+{
-+	return a->mode;
-+}
-+
-+static const struct attribute_group max31785_group = {
-+	.attrs = max31785_attrs,
-+	.is_visible = max31785_attrs_visible,
-+};
-+__ATTRIBUTE_GROUPS(max31785);
-+
-+static int max31785_init_client(struct i2c_client *client,
-+				struct max31785_data *data)
-+{
-+	int i, rv;
-+
-+	for (i = 0; i < NR_CHANNEL; i++) {
-+		rv = max31785_read_fan_data(client, i,
-+				MAX31785_REG_FAN_CONFIG_1_2, 1);
-+		if (rv < 0)
-+			return rv;
-+		data->fan_config[i] = rv;
-+
-+		rv = max31785_read_fan_data(client, i,
-+				MAX31785_REG_FAN_COMMAND_1, 0);
-+		if (rv < 0)
-+			return rv;
-+		data->fan_command[i] = rv;
-+
-+		rv = max31785_read_fan_data(client, i,
-+				MAX31785_REG_MFR_FAN_CONFIG, 1);
-+		if (rv < 0)
-+			return rv;
-+		data->mfr_fan_config[i] = rv;
-+
-+		if (!((data->fan_config[i]
-+			& MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+			|| is_automatic_control_mode(data, i))) {
-+			data->pwm[i] = 0;
-+		}
-+	}
-+
-+	return rv;
-+}
-+
-+/* Return 0 if detection is successful, -ENODEV otherwise */
-+static int max31785_detect(struct i2c_client *client,
-+			  struct i2c_board_info *info)
-+{
-+	struct i2c_adapter *adapter = client->adapter;
-+	int rv;
-+
-+	if (!i2c_check_functionality(adapter,
-+			I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
-+		return -ENODEV;
-+
-+	/* Probe manufacturer / model registers */
-+	rv = i2c_smbus_read_byte_data(client, MAX31785_REG_MFR_ID);
-+	if (rv < 0)
-+		return -ENODEV;
-+	if (rv != MAX31785_MFR_ID)
-+		return -ENODEV;
-+
-+	rv = i2c_smbus_read_byte_data(client, MAX31785_REG_MFR_MODEL);
-+	if (rv < 0)
-+		return -ENODEV;
-+	if (rv != MAX31785_MFR_MODEL)
-+		return -ENODEV;
-+
-+	strlcpy(info->type, "max31785", I2C_NAME_SIZE);
-+
-+	return 0;
-+}
-+
-+static int max31785_probe(struct i2c_client *client,
-+			  const struct i2c_device_id *id)
-+{
-+	struct i2c_adapter *adapter = client->adapter;
-+	struct device *dev = &client->dev;
-+	struct max31785_data *data;
-+	struct device *hwmon_dev;
-+	int err;
-+
-+	if (!i2c_check_functionality(adapter,
-+			I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
-+		return -ENODEV;
-+
-+	data = devm_kzalloc(dev, sizeof(struct max31785_data), GFP_KERNEL);
-+	if (!data)
-+		return -ENOMEM;
-+
-+	data->client = client;
-+	mutex_init(&data->device_lock);
-+
-+	/*
-+	 * Initialize the max31785 chip
-+	 */
-+	err = max31785_init_client(client, data);
-+	if (err)
-+		return err;
-+
-+	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
-+			client->name, data, max31785_groups);
-+
-+	return PTR_ERR_OR_ZERO(hwmon_dev);
-+}
-+
-+static const struct i2c_device_id max31785_id[] = {
-+	{ "max31785", 0 },
-+	{ }
-+};
-+MODULE_DEVICE_TABLE(i2c, max31785_id);
-+
-+static struct i2c_driver max31785_driver = {
-+	.class		= I2C_CLASS_HWMON,
-+	.probe		= max31785_probe,
-+	.driver = {
-+		.name	= "max31785",
-+	},
-+	.id_table	= max31785_id,
-+	.detect		= max31785_detect,
-+	.address_list	= normal_i2c,
-+};
-+
-+module_i2c_driver(max31785_driver);
-+
-+MODULE_AUTHOR("Timothy Pearson <tpearson@raptorengineering.com>");
-+MODULE_DESCRIPTION("MAX31785 sensor driver");
-+MODULE_LICENSE("GPL");
--- 
-1.8.3.1
-
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-1-3-drivers-fsi-sbefifo-Add-in-kernel-API.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-1-3-drivers-fsi-sbefifo-Add-in-kernel-API.patch
deleted file mode 100644
index 70a11f2..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-1-3-drivers-fsi-sbefifo-Add-in-kernel-API.patch
+++ /dev/null
@@ -1,338 +0,0 @@
-From patchwork Fri May 12 19:38:18 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux,dev-4.10,1/3] drivers: fsi: sbefifo: Add in-kernel API
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 761836
-Message-Id: <1494617900-32369-2-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, bradleyb@fuzziesquirrel.com,
- cbostic@linux.vnet.ibm.com
-Date: Fri, 12 May 2017 14:38:18 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-Add exported functions to the SBEFIFO driver to open/write/read/close
-from within the kernel.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/fsi/fsi-sbefifo.c   | 161 +++++++++++++++++++++++++++++++++++---------
- include/linux/fsi-sbefifo.h |  30 +++++++++
- 2 files changed, 161 insertions(+), 30 deletions(-)
- create mode 100644 include/linux/fsi-sbefifo.h
-
-diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
-index b49aec2..56e6331 100644
---- a/drivers/fsi/fsi-sbefifo.c
-+++ b/drivers/fsi/fsi-sbefifo.c
-@@ -15,9 +15,12 @@
- #include <linux/errno.h>
- #include <linux/idr.h>
- #include <linux/fsi.h>
-+#include <linux/fsi-sbefifo.h>
- #include <linux/list.h>
- #include <linux/miscdevice.h>
- #include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_platform.h>
- #include <linux/poll.h>
- #include <linux/sched.h>
- #include <linux/slab.h>
-@@ -82,6 +85,7 @@ struct sbefifo_client {
- 	struct list_head xfrs;
- 	struct sbefifo *dev;
- 	struct kref kref;
-+	unsigned long f_flags;
- };
- 
- static struct list_head sbefifo_fifos;
-@@ -506,6 +510,7 @@ static int sbefifo_open(struct inode *inode, struct file *file)
- 		return -ENOMEM;
- 
- 	file->private_data = client;
-+	client->f_flags = file->f_flags;
- 
- 	return 0;
- }
-@@ -530,24 +535,18 @@ static unsigned int sbefifo_poll(struct file *file, poll_table *wait)
- 	return mask;
- }
- 
--static ssize_t sbefifo_read(struct file *file, char __user *buf,
--		size_t len, loff_t *offset)
-+static ssize_t sbefifo_read_common(struct sbefifo_client *client,
-+				   char __user *ubuf, char *kbuf, size_t len)
- {
--	struct sbefifo_client *client = file->private_data;
- 	struct sbefifo *sbefifo = client->dev;
- 	struct sbefifo_xfr *xfr;
--	ssize_t ret = 0;
- 	size_t n;
--
--	WARN_ON(*offset);
--
--	if (!access_ok(VERIFY_WRITE, buf, len))
--		return -EFAULT;
-+	ssize_t ret = 0;
- 
- 	if ((len >> 2) << 2 != len)
- 		return -EINVAL;
- 
--	if ((file->f_flags & O_NONBLOCK) && !sbefifo_xfr_rsp_pending(client))
-+	if ((client->f_flags & O_NONBLOCK) && !sbefifo_xfr_rsp_pending(client))
- 		return -EAGAIN;
- 
- 	sbefifo_get_client(client);
-@@ -566,10 +565,13 @@ static ssize_t sbefifo_read(struct file *file, char __user *buf,
- 
- 	n = min_t(size_t, n, len);
- 
--	if (copy_to_user(buf, READ_ONCE(client->rbuf.rpos), n)) {
--		sbefifo_put_client(client);
--		return -EFAULT;
--	}
-+	if (ubuf) {
-+		if (copy_to_user(ubuf, READ_ONCE(client->rbuf.rpos), n)) {
-+			sbefifo_put_client(client);
-+			return -EFAULT;
-+		}
-+	} else
-+		memcpy(kbuf, READ_ONCE(client->rbuf.rpos), n);
- 
- 	if (sbefifo_buf_readnb(&client->rbuf, n)) {
- 		xfr = sbefifo_client_next_xfr(client);
-@@ -592,20 +594,28 @@ static ssize_t sbefifo_read(struct file *file, char __user *buf,
- 	return n;
- }
- 
--static ssize_t sbefifo_write(struct file *file, const char __user *buf,
-+static ssize_t sbefifo_read(struct file *file, char __user *buf,
- 		size_t len, loff_t *offset)
- {
- 	struct sbefifo_client *client = file->private_data;
--	struct sbefifo *sbefifo = client->dev;
--	struct sbefifo_xfr *xfr;
--	ssize_t ret = 0;
--	size_t n;
- 
- 	WARN_ON(*offset);
- 
--	if (!access_ok(VERIFY_READ, buf, len))
-+	if (!access_ok(VERIFY_WRITE, buf, len))
- 		return -EFAULT;
- 
-+	return sbefifo_read_common(client, buf, NULL, len);
-+}
-+
-+static ssize_t sbefifo_write_common(struct sbefifo_client *client,
-+				    const char __user *ubuf, const char *kbuf,
-+				    size_t len)
-+{
-+	struct sbefifo *sbefifo = client->dev;
-+	struct sbefifo_xfr *xfr;
-+	ssize_t ret = 0;
-+	size_t n;
-+
- 	if ((len >> 2) << 2 != len)
- 		return -EINVAL;
- 
-@@ -617,7 +627,7 @@ static ssize_t sbefifo_write(struct file *file, const char __user *buf,
- 	spin_lock_irq(&sbefifo->lock);
- 	xfr = sbefifo_next_xfr(sbefifo);
- 
--	if ((file->f_flags & O_NONBLOCK) && xfr && n < len) {
-+	if ((client->f_flags & O_NONBLOCK) && xfr && n < len) {
- 		spin_unlock_irq(&sbefifo->lock);
- 		return -EAGAIN;
- 	}
-@@ -657,18 +667,25 @@ static ssize_t sbefifo_write(struct file *file, const char __user *buf,
- 
- 		n = min_t(size_t, n, len);
- 
--		if (copy_from_user(READ_ONCE(client->wbuf.wpos), buf, n)) {
--			set_bit(SBEFIFO_XFR_CANCEL, &xfr->flags);
--			sbefifo_get(sbefifo);
--			if (mod_timer(&sbefifo->poll_timer, jiffies))
--				sbefifo_put(sbefifo);
--			sbefifo_put_client(client);
--			return -EFAULT;
-+		if (ubuf) {
-+			if (copy_from_user(READ_ONCE(client->wbuf.wpos), ubuf,
-+			    n)) {
-+				set_bit(SBEFIFO_XFR_CANCEL, &xfr->flags);
-+				sbefifo_get(sbefifo);
-+				if (mod_timer(&sbefifo->poll_timer, jiffies))
-+					sbefifo_put(sbefifo);
-+				sbefifo_put_client(client);
-+				return -EFAULT;
-+			}
-+
-+			ubuf += n;
-+		} else {
-+			memcpy(READ_ONCE(client->wbuf.wpos), kbuf, n);
-+			kbuf += n;
- 		}
- 
- 		sbefifo_buf_wrotenb(&client->wbuf, n);
- 		len -= n;
--		buf += n;
- 		ret += n;
- 
- 		/*
-@@ -685,6 +702,19 @@ static ssize_t sbefifo_write(struct file *file, const char __user *buf,
- 	return ret;
- }
- 
-+static ssize_t sbefifo_write(struct file *file, const char __user *buf,
-+		size_t len, loff_t *offset)
-+{
-+	struct sbefifo_client *client = file->private_data;
-+
-+	WARN_ON(*offset);
-+
-+	if (!access_ok(VERIFY_READ, buf, len))
-+		return -EFAULT;
-+
-+	return sbefifo_write_common(client, buf, NULL, len);
-+}
-+
- static int sbefifo_release(struct inode *inode, struct file *file)
- {
- 	struct sbefifo_client *client = file->private_data;
-@@ -704,12 +734,68 @@ static int sbefifo_release(struct inode *inode, struct file *file)
- 	.release	= sbefifo_release,
- };
- 
-+struct sbefifo_client *sbefifo_drv_open(struct device *dev,
-+					unsigned long flags)
-+{
-+	struct sbefifo_client *client = NULL;
-+	struct sbefifo *sbefifo;
-+	struct fsi_device *fsi_dev = to_fsi_dev(dev);
-+
-+	list_for_each_entry(sbefifo, &sbefifo_fifos, link) {
-+		if (sbefifo->fsi_dev != fsi_dev)
-+			continue;
-+
-+		client = sbefifo_new_client(sbefifo);
-+		if (client)
-+			client->f_flags = flags;
-+	}
-+
-+	return client;
-+}
-+EXPORT_SYMBOL_GPL(sbefifo_drv_open);
-+
-+int sbefifo_drv_read(struct sbefifo_client *client, char *buf, size_t len)
-+{
-+	return sbefifo_read_common(client, NULL, buf, len);
-+}
-+EXPORT_SYMBOL_GPL(sbefifo_drv_read);
-+
-+int sbefifo_drv_write(struct sbefifo_client *client, const char *buf,
-+		      size_t len)
-+{
-+	return sbefifo_write_common(client, NULL, buf, len);
-+}
-+EXPORT_SYMBOL_GPL(sbefifo_drv_write);
-+
-+void sbefifo_drv_release(struct sbefifo_client *client)
-+{
-+	if (!client)
-+		return;
-+
-+	sbefifo_put_client(client);
-+}
-+EXPORT_SYMBOL_GPL(sbefifo_drv_release);
-+
-+static int sbefifo_unregister_child(struct device *dev, void *data)
-+{
-+	struct platform_device *child = to_platform_device(dev);
-+
-+	of_device_unregister(child);
-+	if (dev->of_node)
-+		of_node_clear_flag(dev->of_node, OF_POPULATED);
-+
-+	return 0;
-+}
-+
- static int sbefifo_probe(struct device *dev)
- {
- 	struct fsi_device *fsi_dev = to_fsi_dev(dev);
- 	struct sbefifo *sbefifo;
-+	struct device_node *np;
-+	struct platform_device *child;
-+	char child_name[32];
- 	u32 sts;
--	int ret;
-+	int ret, child_idx = 0;
- 
- 	dev_info(dev, "Found sbefifo device\n");
- 	sbefifo = kzalloc(sizeof(*sbefifo), GFP_KERNEL);
-@@ -750,6 +836,18 @@ static int sbefifo_probe(struct device *dev)
- 	init_waitqueue_head(&sbefifo->wait);
- 	INIT_LIST_HEAD(&sbefifo->xfrs);
- 
-+	if (dev->of_node) {
-+		/* create platform devs for dts child nodes (occ, etc) */
-+		for_each_child_of_node(dev->of_node, np) {
-+			snprintf(child_name, sizeof(child_name), "%s-dev%d",
-+				 sbefifo->name, child_idx++);
-+			child = of_platform_device_create(np, child_name, dev);
-+			if (!child)
-+				dev_warn(&sbefifo->fsi_dev->dev,
-+					 "failed to create child node dev\n");
-+		}
-+	}
-+
- 	/* This bit of silicon doesn't offer any interrupts... */
- 	setup_timer(&sbefifo->poll_timer, sbefifo_poll_timer,
- 			(unsigned long)sbefifo);
-@@ -767,6 +865,9 @@ static int sbefifo_remove(struct device *dev)
- 	list_for_each_entry_safe(sbefifo, sbefifo_tmp, &sbefifo_fifos, link) {
- 		if (sbefifo->fsi_dev != fsi_dev)
- 			continue;
-+
-+		device_for_each_child(dev, NULL, sbefifo_unregister_child);
-+
- 		misc_deregister(&sbefifo->mdev);
- 		list_del(&sbefifo->link);
- 		ida_simple_remove(&sbefifo_ida, sbefifo->idx);
-diff --git a/include/linux/fsi-sbefifo.h b/include/linux/fsi-sbefifo.h
-new file mode 100644
-index 0000000..1b46c63
---- /dev/null
-+++ b/include/linux/fsi-sbefifo.h
-@@ -0,0 +1,30 @@
-+/*
-+ * SBEFIFO FSI Client device driver
-+ *
-+ * Copyright (C) IBM Corporation 2017
-+ *
-+ * 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
-+ * MERGCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef __FSI_SBEFIFO_H__
-+#define __FSI_SBEFIFO_H__
-+
-+struct device;
-+struct sbefifo_client;
-+
-+extern struct sbefifo_client *sbefifo_drv_open(struct device *dev,
-+					       unsigned long flags);
-+extern int sbefifo_drv_read(struct sbefifo_client *client, char *buf,
-+			    size_t len);
-+extern int sbefifo_drv_write(struct sbefifo_client *client, const char *buf,
-+			     size_t len);
-+extern void sbefifo_drv_release(struct sbefifo_client *client);
-+
-+#endif /* __FSI_SBEFIFO_H__ */
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-2-3-drivers-fsi-sbefifo-Add-OCC-driver.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-2-3-drivers-fsi-sbefifo-Add-OCC-driver.patch
deleted file mode 100644
index 5c53dad..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-2-3-drivers-fsi-sbefifo-Add-OCC-driver.patch
+++ /dev/null
@@ -1,694 +0,0 @@
-From patchwork Fri May 12 19:38:19 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux,dev-4.10,2/3] drivers: fsi: sbefifo: Add OCC driver
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 761838
-Message-Id: <1494617900-32369-3-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, bradleyb@fuzziesquirrel.com,
- cbostic@linux.vnet.ibm.com
-Date: Fri, 12 May 2017 14:38:19 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-This driver provides an atomic communications channel between the OCC on
-the POWER9 processor and a service processor (a BMC). The driver is
-dependent on the FSI SBEIFO driver to get hardware access to the OCC
-SRAM.
-
-The format of the communication is a command followed by a response.
-Since the command and response must be performed atomically, the driver
-will perform this operations asynchronously. In this way, a write
-operation starts the command, and a read will gather the response data
-once it is complete.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/fsi/Kconfig  |   9 +
- drivers/fsi/Makefile |   1 +
- drivers/fsi/occ.c    | 625 +++++++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 635 insertions(+)
- create mode 100644 drivers/fsi/occ.c
-
-diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
-index 39527fa..f3d8593 100644
---- a/drivers/fsi/Kconfig
-+++ b/drivers/fsi/Kconfig
-@@ -36,6 +36,15 @@ config FSI_SBEFIFO
- 	---help---
- 	This option enables an FSI based SBEFIFO device driver.
- 
-+if FSI_SBEFIFO
-+
-+config OCCFIFO
-+	tristate "OCC SBEFIFO client device driver"
-+	---help---
-+	This option enables an SBEFIFO based OCC device driver.
-+
-+endif
-+
- endif
- 
- endmenu
-diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
-index 851182e..336d9d5 100644
---- a/drivers/fsi/Makefile
-+++ b/drivers/fsi/Makefile
-@@ -4,3 +4,4 @@ obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o
- obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
- obj-$(CONFIG_FSI_SCOM) += fsi-scom.o
- obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.o
-+obj-$(CONFIG_OCCFIFO) += occ.o
-diff --git a/drivers/fsi/occ.c b/drivers/fsi/occ.c
-new file mode 100644
-index 0000000..74272c8
---- /dev/null
-+++ b/drivers/fsi/occ.c
-@@ -0,0 +1,625 @@
-+/*
-+ * Copyright 2017 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.
-+ */
-+
-+#include <asm/unaligned.h>
-+#include <linux/device.h>
-+#include <linux/err.h>
-+#include <linux/fsi-sbefifo.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/wait.h>
-+#include <linux/workqueue.h>
-+
-+#define OCC_SRAM_BYTES		4096
-+#define OCC_CMD_DATA_BYTES	4090
-+#define OCC_RESP_DATA_BYTES	4089
-+
-+struct occ {
-+	struct device *sbefifo;
-+	char name[32];
-+	int idx;
-+	struct miscdevice mdev;
-+	struct list_head xfrs;
-+	spinlock_t list_lock;
-+	spinlock_t occ_lock;
-+	struct work_struct work;
-+};
-+
-+#define to_occ(x)	container_of((x), struct occ, mdev)
-+
-+struct occ_command {
-+	u8 seq_no;
-+	u8 cmd_type;
-+	u16 data_length;
-+	u8 data[OCC_CMD_DATA_BYTES];
-+	u16 checksum;
-+};
-+
-+struct occ_response {
-+	u8 seq_no;
-+	u8 cmd_type;
-+	u8 return_status;
-+	u16 data_length;
-+	u8 data[OCC_RESP_DATA_BYTES];
-+	u16 checksum;
-+};
-+
-+struct occ_xfr;
-+
-+enum {
-+	CLIENT_NONBLOCKING,
-+};
-+
-+struct occ_client {
-+	struct occ *occ;
-+	struct occ_xfr *xfr;
-+	spinlock_t lock;
-+	wait_queue_head_t wait;
-+	size_t read_offset;
-+	unsigned long flags;
-+};
-+
-+enum {
-+	XFR_IN_PROGRESS,
-+	XFR_COMPLETE,
-+	XFR_CANCELED,
-+	XFR_WAITING,
-+};
-+
-+struct occ_xfr {
-+	struct list_head link;
-+	struct occ_client *client;
-+	int rc;
-+	u8 buf[OCC_SRAM_BYTES];
-+	size_t cmd_data_length;
-+	size_t resp_data_length;
-+	unsigned long flags;
-+};
-+
-+static struct workqueue_struct *occ_wq;
-+
-+static DEFINE_IDA(occ_ida);
-+
-+static void occ_enqueue_xfr(struct occ_xfr *xfr)
-+{
-+	int empty;
-+	struct occ *occ = xfr->client->occ;
-+
-+	spin_lock_irq(&occ->list_lock);
-+	empty = list_empty(&occ->xfrs);
-+	list_add_tail(&xfr->link, &occ->xfrs);
-+	spin_unlock(&occ->list_lock);
-+
-+	if (empty)
-+		queue_work(occ_wq, &occ->work);
-+}
-+
-+static int occ_open(struct inode *inode, struct file *file)
-+{
-+	struct occ_client *client;
-+	struct miscdevice *mdev = file->private_data;
-+	struct occ *occ = to_occ(mdev);
-+
-+	client = kzalloc(sizeof(*client), GFP_KERNEL);
-+	if (!client)
-+		return -ENOMEM;
-+
-+	client->occ = occ;
-+	spin_lock_init(&client->lock);
-+	init_waitqueue_head(&client->wait);
-+
-+	if (file->f_flags & O_NONBLOCK)
-+		set_bit(CLIENT_NONBLOCKING, &client->flags);
-+
-+	file->private_data = client;
-+
-+	return 0;
-+}
-+
-+static ssize_t occ_read(struct file *file, char __user *buf, size_t len,
-+			loff_t *offset)
-+{
-+	int rc;
-+	size_t bytes;
-+	struct occ_xfr *xfr;
-+	struct occ_client *client = file->private_data;
-+
-+	if (!access_ok(VERIFY_WRITE, buf, len))
-+		return -EFAULT;
-+
-+	if (len > OCC_SRAM_BYTES)
-+		return -EINVAL;
-+
-+	spin_lock_irq(&client->lock);
-+	if (!client->xfr) {
-+		/* we just finished reading all data, return 0 */
-+		if (client->read_offset) {
-+			rc = 0;
-+			client->read_offset = 0;
-+		} else
-+			rc = -ENOMSG;
-+
-+		goto done;
-+	}
-+
-+	xfr = client->xfr;
-+
-+	if (!test_bit(XFR_COMPLETE, &xfr->flags)) {
-+		if (client->flags & CLIENT_NONBLOCKING) {
-+			rc = -ERESTARTSYS;
-+			goto done;
-+		}
-+
-+		set_bit(XFR_WAITING, &xfr->flags);
-+		spin_unlock(&client->lock);
-+
-+		rc = wait_event_interruptible(client->wait,
-+			test_bit(XFR_COMPLETE, &xfr->flags) ||
-+			test_bit(XFR_CANCELED, &xfr->flags));
-+
-+		spin_lock_irq(&client->lock);
-+		if (test_bit(XFR_CANCELED, &xfr->flags)) {
-+			kfree(xfr);
-+			spin_unlock(&client->lock);
-+			kfree(client);
-+			return -EBADFD;
-+		}
-+
-+		clear_bit(XFR_WAITING, &xfr->flags);
-+		if (!test_bit(XFR_COMPLETE, &xfr->flags)) {
-+			rc = -EINTR;
-+			goto done;
-+		}
-+	}
-+
-+	if (xfr->rc) {
-+		rc = xfr->rc;
-+		goto done;
-+	}
-+
-+	bytes = min(len, xfr->resp_data_length - client->read_offset);
-+	if (copy_to_user(buf, &xfr->buf[client->read_offset], bytes)) {
-+		rc = -EFAULT;
-+		goto done;
-+	}
-+
-+	client->read_offset += bytes;
-+
-+	/* xfr done */
-+	if (client->read_offset == xfr->resp_data_length) {
-+		kfree(xfr);
-+		client->xfr = NULL;
-+	}
-+
-+	rc = bytes;
-+
-+done:
-+	spin_unlock(&client->lock);
-+	return rc;
-+}
-+
-+static ssize_t occ_write(struct file *file, const char __user *buf,
-+			 size_t len, loff_t *offset)
-+{
-+	int rc;
-+	struct occ_xfr *xfr;
-+	struct occ_client *client = file->private_data;
-+
-+	if (!access_ok(VERIFY_READ, buf, len))
-+		return -EFAULT;
-+
-+	if (len > OCC_SRAM_BYTES)
-+		return -EINVAL;
-+
-+	spin_lock_irq(&client->lock);
-+	if (client->xfr) {
-+		rc = -EDEADLK;
-+		goto done;
-+	}
-+
-+	xfr = kzalloc(sizeof(*xfr), GFP_KERNEL);
-+	if (!xfr) {
-+		rc = -ENOMEM;
-+		goto done;
-+	}
-+
-+	if (copy_from_user(xfr->buf, buf, len)) {
-+		kfree(xfr);
-+		rc = -EFAULT;
-+		goto done;
-+	}
-+
-+	xfr->client = client;
-+	xfr->cmd_data_length = len;
-+	client->xfr = xfr;
-+	client->read_offset = 0;
-+
-+	occ_enqueue_xfr(xfr);
-+
-+	rc = len;
-+
-+done:
-+	spin_unlock(&client->lock);
-+	return rc;
-+}
-+
-+static int occ_release(struct inode *inode, struct file *file)
-+{
-+	struct occ_xfr *xfr;
-+	struct occ_client *client = file->private_data;
-+	struct occ *occ = client->occ;
-+
-+	spin_lock_irq(&client->lock);
-+	xfr = client->xfr;
-+	if (!xfr) {
-+		spin_unlock(&client->lock);
-+		kfree(client);
-+		return 0;
-+	}
-+
-+	spin_lock_irq(&occ->list_lock);
-+	set_bit(XFR_CANCELED, &xfr->flags);
-+	if (!test_bit(XFR_IN_PROGRESS, &xfr->flags)) {
-+		/* already deleted from list if complete */
-+		if (!test_bit(XFR_COMPLETE, &xfr->flags))
-+			list_del(&xfr->link);
-+
-+		spin_unlock(&occ->list_lock);
-+
-+		if (test_bit(XFR_WAITING, &xfr->flags)) {
-+			/* blocking read; let reader clean up */
-+			wake_up_interruptible(&client->wait);
-+			spin_unlock(&client->lock);
-+			return 0;
-+		}
-+
-+		kfree(xfr);
-+		spin_unlock(&client->lock);
-+		kfree(client);
-+		return 0;
-+	}
-+
-+	/* operation is in progress; let worker clean up*/
-+	spin_unlock(&occ->list_lock);
-+	spin_unlock(&client->lock);
-+	return 0;
-+}
-+
-+static const struct file_operations occ_fops = {
-+	.owner = THIS_MODULE,
-+	.open = occ_open,
-+	.read = occ_read,
-+	.write = occ_write,
-+	.release = occ_release,
-+};
-+
-+static int occ_getscom(struct device *sbefifo, u32 address, u8 *data)
-+{
-+	int rc;
-+	u32 buf[4];
-+	struct sbefifo_client *client;
-+	const size_t len = sizeof(buf);
-+
-+	buf[0] = cpu_to_be32(0x4);
-+	buf[1] = cpu_to_be32(0xa201);
-+	buf[2] = 0;
-+	buf[3] = cpu_to_be32(address);
-+
-+	client = sbefifo_drv_open(sbefifo, 0);
-+	if (!client)
-+		return -ENODEV;
-+
-+	rc = sbefifo_drv_write(client, (const char *)buf, len);
-+	if (rc < 0)
-+		goto done;
-+	else if (rc != len) {
-+		rc = -EMSGSIZE;
-+		goto done;
-+	}
-+
-+	rc = sbefifo_drv_read(client, (char *)buf, len);
-+	if (rc < 0)
-+		goto done;
-+	else if (rc != len) {
-+		rc = -EMSGSIZE;
-+		goto done;
-+	}
-+
-+	/* check for good response */
-+	if ((be32_to_cpu(buf[2]) >> 16) != 0xC0DE) {
-+		rc = -EFAULT;
-+		goto done;
-+	}
-+
-+	rc = 0;
-+
-+	memcpy(data, buf, sizeof(u64));
-+
-+done:
-+	sbefifo_drv_release(client);
-+	return rc;
-+}
-+
-+static int occ_putscom(struct device *sbefifo, u32 address, u8 *data)
-+{
-+	int rc;
-+	u32 buf[6];
-+	struct sbefifo_client *client;
-+	const size_t len = sizeof(buf);
-+
-+	buf[0] = cpu_to_be32(0x6);
-+	buf[1] = cpu_to_be32(0xa202);
-+	buf[2] = 0;
-+	buf[3] = cpu_to_be32(address);
-+	memcpy(&buf[4], data, sizeof(u64));
-+
-+	client = sbefifo_drv_open(sbefifo, 0);
-+	if (!client)
-+		return -ENODEV;
-+
-+	rc = sbefifo_drv_write(client, (const char *)buf, len);
-+	if (rc < 0)
-+		goto done;
-+	else if (rc != len) {
-+		rc = -EMSGSIZE;
-+		goto done;
-+	}
-+
-+	rc = 0;
-+
-+	/* ignore response */
-+	sbefifo_drv_read(client, (char *)buf, len);
-+
-+done:
-+	sbefifo_drv_release(client);
-+	return rc;
-+}
-+
-+static int occ_putscom_u32(struct device *sbefifo, u32 address, u32 data0,
-+			   u32 data1)
-+{
-+	u8 buf[8];
-+	u32 raw_data0 = cpu_to_be32(data0), raw_data1 = cpu_to_be32(data1);
-+
-+	memcpy(buf, &raw_data0, 4);
-+	memcpy(buf + 4, &raw_data1, 4);
-+
-+	return occ_putscom(sbefifo, address, buf);
-+}
-+
-+static void occ_worker(struct work_struct *work)
-+{
-+	int i, empty, canceled, waiting, rc;
-+	u16 resp_data_length;
-+	struct occ *occ = container_of(work, struct occ, work);
-+	struct device *sbefifo = occ->sbefifo;
-+	struct occ_client *client;
-+	struct occ_xfr *xfr;
-+	struct occ_response *resp;
-+
-+again:
-+	spin_lock_irq(&occ->list_lock);
-+	xfr = list_first_entry(&occ->xfrs, struct occ_xfr, link);
-+	if (!xfr) {
-+		spin_unlock(&occ->list_lock);
-+		return;
-+	}
-+
-+	set_bit(XFR_IN_PROGRESS, &xfr->flags);
-+	spin_unlock(&occ->list_lock);
-+
-+	resp = (struct occ_response *)xfr->buf;
-+
-+	spin_lock_irq(&occ->occ_lock);
-+
-+	/* set address reg to occ sram command buffer */
-+	rc = occ_putscom_u32(sbefifo, 0x6D050, 0xFFFBE000, 0);
-+	if (rc)
-+		goto done;
-+
-+	/* write cmd data */
-+	for (i = 0; i < xfr->cmd_data_length; i += 8) {
-+		rc = occ_putscom(sbefifo, 0x6D055, &xfr->buf[i]);
-+		if (rc)
-+			goto done;
-+	}
-+
-+	/* trigger attention */
-+	rc = occ_putscom_u32(sbefifo, 0x6D035, 0x20010000, 0);
-+	if (rc)
-+		goto done;
-+
-+	/* set address reg to occ sram response buffer */
-+	rc = occ_putscom_u32(sbefifo, 0x6D050, 0xFFFBF000, 0);
-+	if (rc)
-+		goto done;
-+
-+	rc = occ_getscom(sbefifo, 0x6D055, xfr->buf);
-+	if (rc)
-+		goto done;
-+
-+	xfr->resp_data_length += 8;
-+
-+	resp_data_length = be16_to_cpu(get_unaligned(&resp->data_length));
-+	if (resp_data_length > OCC_RESP_DATA_BYTES) {
-+		rc = -EFAULT;
-+		goto done;
-+	}
-+
-+	/* already read 3 bytes of resp data, but also need 2 bytes chksum */
-+	for (i = 8; i < resp_data_length + 7; i += 8) {
-+		rc = occ_getscom(sbefifo, 0x6D055, &xfr->buf[i]);
-+		if (rc)
-+			goto done;
-+
-+		xfr->resp_data_length += 8;
-+	}
-+
-+	/* no errors, got all data */
-+	xfr->resp_data_length = resp_data_length + 7;
-+
-+done:
-+	spin_unlock(&occ->occ_lock);
-+
-+	xfr->rc = rc;
-+	client = xfr->client;
-+
-+	/* lock client to prevent race with read() */
-+	spin_lock_irq(&client->lock);
-+	set_bit(XFR_COMPLETE, &xfr->flags);
-+	waiting = test_bit(XFR_WAITING, &xfr->flags);
-+	spin_unlock(&client->lock);
-+
-+	spin_lock_irq(&occ->list_lock);
-+	clear_bit(XFR_IN_PROGRESS, &xfr->flags);
-+	list_del(&xfr->link);
-+	empty = list_empty(&occ->xfrs);
-+	canceled = test_bit(XFR_CANCELED, &xfr->flags);
-+	spin_unlock(&occ->list_lock);
-+
-+	if (waiting)
-+		wake_up_interruptible(&client->wait);
-+	else if (canceled) {
-+		kfree(xfr);
-+		kfree(xfr->client);
-+	}
-+
-+	if (!empty)
-+		goto again;
-+}
-+
-+static int occ_probe(struct platform_device *pdev)
-+{
-+	int rc;
-+	u32 reg;
-+	struct occ *occ;
-+	struct device *dev = &pdev->dev;
-+
-+	dev_info(dev, "Found occ device\n");
-+	occ = devm_kzalloc(dev, sizeof(*occ), GFP_KERNEL);
-+	if (!occ)
-+		return -ENOMEM;
-+
-+	occ->sbefifo = dev->parent;
-+	INIT_LIST_HEAD(&occ->xfrs);
-+	spin_lock_init(&occ->list_lock);
-+	spin_lock_init(&occ->occ_lock);
-+	INIT_WORK(&occ->work, occ_worker);
-+
-+	if (dev->of_node) {
-+		rc = of_property_read_u32(dev->of_node, "reg", &reg);
-+		if (!rc) {
-+			/* make sure we don't have a duplicate from dts */
-+			occ->idx = ida_simple_get(&occ_ida, reg, reg + 1,
-+						  GFP_KERNEL);
-+			if (occ->idx < 0)
-+				occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX,
-+							  GFP_KERNEL);
-+		} else
-+			occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX,
-+						  GFP_KERNEL);
-+	} else
-+		occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX, GFP_KERNEL);
-+
-+	snprintf(occ->name, sizeof(occ->name), "occ%d", occ->idx);
-+	occ->mdev.fops = &occ_fops;
-+	occ->mdev.minor = MISC_DYNAMIC_MINOR;
-+	occ->mdev.name = occ->name;
-+	occ->mdev.parent = dev;
-+
-+	rc = misc_register(&occ->mdev);
-+	if (rc) {
-+		dev_err(dev, "failed to register miscdevice\n");
-+		return rc;
-+	}
-+
-+	platform_set_drvdata(pdev, occ);
-+
-+	return 0;
-+}
-+
-+static int occ_remove(struct platform_device *pdev)
-+{
-+	struct occ_xfr *xfr, *tmp;
-+	struct occ *occ = platform_get_drvdata(pdev);
-+	struct occ_client *client;
-+
-+	misc_deregister(&occ->mdev);
-+
-+	spin_lock_irq(&occ->list_lock);
-+	list_for_each_entry_safe(xfr, tmp, &occ->xfrs, link) {
-+		client = xfr->client;
-+		set_bit(XFR_CANCELED, &xfr->flags);
-+
-+		if (!test_bit(XFR_IN_PROGRESS, &xfr->flags)) {
-+			list_del(&xfr->link);
-+
-+			spin_lock_irq(&client->lock);
-+			if (test_bit(XFR_WAITING, &xfr->flags)) {
-+				wake_up_interruptible(&client->wait);
-+				spin_unlock(&client->lock);
-+			} else {
-+				kfree(xfr);
-+				spin_unlock(&client->lock);
-+				kfree(client);
-+			}
-+		}
-+	}
-+	spin_unlock(&occ->list_lock);
-+
-+	flush_work(&occ->work);
-+
-+	ida_simple_remove(&occ_ida, occ->idx);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id occ_match[] = {
-+	{ .compatible = "ibm,p9-occ" },
-+	{ },
-+};
-+
-+static struct platform_driver occ_driver = {
-+	.driver = {
-+		.name = "occ",
-+		.of_match_table	= occ_match,
-+	},
-+	.probe	= occ_probe,
-+	.remove = occ_remove,
-+};
-+
-+static int occ_init(void)
-+{
-+	occ_wq = create_singlethread_workqueue("occ");
-+	if (!occ_wq)
-+		return -ENOMEM;
-+
-+	return platform_driver_register(&occ_driver);
-+}
-+
-+static void occ_exit(void)
-+{
-+	destroy_workqueue(occ_wq);
-+
-+	platform_driver_unregister(&occ_driver);
-+}
-+
-+module_init(occ_init);
-+module_exit(occ_exit);
-+
-+MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>");
-+MODULE_DESCRIPTION("BMC P9 OCC driver");
-+MODULE_LICENSE("GPL");
-+
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-drivers-fsi-Add-FSI-SBEFIFO-driver.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-drivers-fsi-Add-FSI-SBEFIFO-driver.patch
deleted file mode 100644
index b29e0e9..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-drivers-fsi-Add-FSI-SBEFIFO-driver.patch
+++ /dev/null
@@ -1,899 +0,0 @@
-From patchwork Thu May 11 02:52:53 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux,dev-4.10] drivers: fsi: Add FSI SBEFIFO driver
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 760920
-Message-Id: <1494471173-6077-1-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, bradleyb@fuzziesquirrel.com
-Date: Wed, 10 May 2017 21:52:53 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-IBM POWER9 processors contain some embedded hardware and software bits
-collectively referred to as the self boot engine (SBE).  One role of
-the SBE is to act as a proxy that provides access to the registers of
-the POWER chip from other (embedded) systems.
-
-The POWER9 chip contains a hardware frontend for communicating with
-the SBE from remote systems called the SBEFIFO.  The SBEFIFO logic
-is contained within an FSI CFAM (see Documentation/fsi) and as such
-the driver implements an FSI bus device.
-
-The SBE expects to communicate using a defined wire protocol; however,
-the driver knows nothing of the protocol and only provides raw access
-to the fifo device to userspace applications wishing to communicate with
-the SBE using the wire protocol.
-
-The SBEFIFO consists of two hardware fifos.  The upstream fifo is used
-by the driver to transfer data to the SBE on the POWER chip, from the
-system hosting the driver.  The downstream fifo is used by the driver to
-transfer data from the SBE on the power chip to the system hosting the
-driver.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
-Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
----
- drivers/fsi/Kconfig       |   5 +
- drivers/fsi/Makefile      |   1 +
- drivers/fsi/fsi-sbefifo.c | 824 ++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 830 insertions(+)
- create mode 100644 drivers/fsi/fsi-sbefifo.c
-
-diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
-index fc031ac..39527fa 100644
---- a/drivers/fsi/Kconfig
-+++ b/drivers/fsi/Kconfig
-@@ -31,6 +31,11 @@ config FSI_SCOM
- 	---help---
- 	This option enables an FSI based SCOM device driver.
- 
-+config FSI_SBEFIFO
-+	tristate "SBEFIFO FSI client device driver"
-+	---help---
-+	This option enables an FSI based SBEFIFO device driver.
-+
- endif
- 
- endmenu
-diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
-index 65eb99d..851182e 100644
---- a/drivers/fsi/Makefile
-+++ b/drivers/fsi/Makefile
-@@ -3,3 +3,4 @@ obj-$(CONFIG_FSI) += fsi-core.o
- obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o
- obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
- obj-$(CONFIG_FSI_SCOM) += fsi-scom.o
-+obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.o
-diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
-new file mode 100644
-index 0000000..b49aec2
---- /dev/null
-+++ b/drivers/fsi/fsi-sbefifo.c
-@@ -0,0 +1,824 @@
-+/*
-+ * Copyright (C) IBM Corporation 2017
-+ *
-+ * 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
-+ * MERGCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+#include <linux/idr.h>
-+#include <linux/fsi.h>
-+#include <linux/list.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/poll.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/timer.h>
-+#include <linux/uaccess.h>
-+
-+/*
-+ * The SBEFIFO is a pipe-like FSI device for communicating with
-+ * the self boot engine on POWER processors.
-+ */
-+
-+#define DEVICE_NAME		"sbefifo"
-+#define FSI_ENGID_SBE		0x22
-+#define SBEFIFO_BUF_CNT		32
-+
-+#define SBEFIFO_UP		0x00	/* Up register offset */
-+#define SBEFIFO_DWN		0x40	/* Down register offset */
-+
-+#define SBEFIFO_STS		0x04
-+#define   SBEFIFO_EMPTY			BIT(20)
-+#define SBEFIFO_EOT_RAISE	0x08
-+#define   SBEFIFO_EOT_MAGIC		0xffffffff
-+#define SBEFIFO_EOT_ACK		0x14
-+
-+struct sbefifo {
-+	struct timer_list poll_timer;
-+	struct fsi_device *fsi_dev;
-+	struct miscdevice mdev;
-+	wait_queue_head_t wait;
-+	struct list_head link;
-+	struct list_head xfrs;
-+	struct kref kref;
-+	spinlock_t lock;
-+	char name[32];
-+	int idx;
-+	int rc;
-+};
-+
-+struct sbefifo_buf {
-+	u32 buf[SBEFIFO_BUF_CNT];
-+	unsigned long flags;
-+#define SBEFIFO_BUF_FULL		1
-+	u32 *rpos;
-+	u32 *wpos;
-+};
-+
-+struct sbefifo_xfr {
-+	struct sbefifo_buf *rbuf;
-+	struct sbefifo_buf *wbuf;
-+	struct list_head client;
-+	struct list_head xfrs;
-+	unsigned long flags;
-+#define SBEFIFO_XFR_WRITE_DONE		1
-+#define SBEFIFO_XFR_RESP_PENDING	2
-+#define SBEFIFO_XFR_COMPLETE		3
-+#define SBEFIFO_XFR_CANCEL		4
-+};
-+
-+struct sbefifo_client {
-+	struct sbefifo_buf rbuf;
-+	struct sbefifo_buf wbuf;
-+	struct list_head xfrs;
-+	struct sbefifo *dev;
-+	struct kref kref;
-+};
-+
-+static struct list_head sbefifo_fifos;
-+
-+static DEFINE_IDA(sbefifo_ida);
-+
-+static int sbefifo_inw(struct sbefifo *sbefifo, int reg, u32 *word)
-+{
-+	int rc;
-+	u32 raw_word;
-+
-+	rc = fsi_device_read(sbefifo->fsi_dev, reg, &raw_word,
-+			     sizeof(raw_word));
-+	if (rc)
-+		return rc;
-+
-+	*word = be32_to_cpu(raw_word);
-+	return 0;
-+}
-+
-+static int sbefifo_outw(struct sbefifo *sbefifo, int reg, u32 word)
-+{
-+	u32 raw_word = cpu_to_be32(word);
-+
-+	return fsi_device_write(sbefifo->fsi_dev, reg, &raw_word,
-+				sizeof(raw_word));
-+}
-+
-+static int sbefifo_readw(struct sbefifo *sbefifo, u32 *word)
-+{
-+	return fsi_device_read(sbefifo->fsi_dev, SBEFIFO_DWN, word,
-+			       sizeof(*word));
-+}
-+
-+static int sbefifo_writew(struct sbefifo *sbefifo, u32 word)
-+{
-+	return fsi_device_write(sbefifo->fsi_dev, SBEFIFO_UP, &word,
-+				sizeof(word));
-+}
-+
-+static int sbefifo_ack_eot(struct sbefifo *sbefifo)
-+{
-+	u32 discard;
-+	int ret;
-+
-+	 /* Discard the EOT word. */
-+	ret = sbefifo_readw(sbefifo, &discard);
-+	if (ret)
-+		return ret;
-+
-+	return sbefifo_outw(sbefifo, SBEFIFO_DWN | SBEFIFO_EOT_ACK,
-+			SBEFIFO_EOT_MAGIC);
-+}
-+
-+static size_t sbefifo_dev_nwreadable(u32 sts)
-+{
-+	static const u32 FIFO_NTRY_CNT_MSK = 0x000f0000;
-+	static const unsigned int FIFO_NTRY_CNT_SHIFT = 16;
-+
-+	return (sts & FIFO_NTRY_CNT_MSK) >> FIFO_NTRY_CNT_SHIFT;
-+}
-+
-+static size_t sbefifo_dev_nwwriteable(u32 sts)
-+{
-+	static const size_t FIFO_DEPTH = 8;
-+
-+	return FIFO_DEPTH - sbefifo_dev_nwreadable(sts);
-+}
-+
-+static void sbefifo_buf_init(struct sbefifo_buf *buf)
-+{
-+	WRITE_ONCE(buf->rpos, buf->buf);
-+	WRITE_ONCE(buf->wpos, buf->buf);
-+}
-+
-+static size_t sbefifo_buf_nbreadable(struct sbefifo_buf *buf)
-+{
-+	size_t n;
-+	u32 *rpos = READ_ONCE(buf->rpos);
-+	u32 *wpos = READ_ONCE(buf->wpos);
-+
-+	if (test_bit(SBEFIFO_BUF_FULL, &buf->flags))
-+		n = SBEFIFO_BUF_CNT;
-+	else if (rpos <= wpos)
-+		n = wpos - rpos;
-+	else
-+		n = (buf->buf + SBEFIFO_BUF_CNT) - rpos;
-+
-+	return n << 2;
-+}
-+
-+static size_t sbefifo_buf_nbwriteable(struct sbefifo_buf *buf)
-+{
-+	size_t n;
-+	u32 *rpos = READ_ONCE(buf->rpos);
-+	u32 *wpos = READ_ONCE(buf->wpos);
-+
-+	if (test_bit(SBEFIFO_BUF_FULL, &buf->flags))
-+		n = 0;
-+	else if (wpos < rpos)
-+		n = rpos - wpos;
-+	else
-+		n = (buf->buf + SBEFIFO_BUF_CNT) - wpos;
-+
-+	return n << 2;
-+}
-+
-+/*
-+ * Update pointers and flags after doing a buffer read.  Return true if the
-+ * buffer is now empty;
-+ */
-+static bool sbefifo_buf_readnb(struct sbefifo_buf *buf, size_t n)
-+{
-+	u32 *rpos = READ_ONCE(buf->rpos);
-+	u32 *wpos = READ_ONCE(buf->wpos);
-+
-+	if (n)
-+		clear_bit(SBEFIFO_BUF_FULL, &buf->flags);
-+
-+	rpos += (n >> 2);
-+	if (rpos == buf->buf + SBEFIFO_BUF_CNT)
-+		rpos = buf->buf;
-+
-+	WRITE_ONCE(buf->rpos, rpos);
-+	return rpos == wpos;
-+}
-+
-+/*
-+ * Update pointers and flags after doing a buffer write.  Return true if the
-+ * buffer is now full.
-+ */
-+static bool sbefifo_buf_wrotenb(struct sbefifo_buf *buf, size_t n)
-+{
-+	u32 *rpos = READ_ONCE(buf->rpos);
-+	u32 *wpos = READ_ONCE(buf->wpos);
-+
-+	wpos += (n >> 2);
-+	if (wpos == buf->buf + SBEFIFO_BUF_CNT)
-+		wpos = buf->buf;
-+	if (wpos == rpos)
-+		set_bit(SBEFIFO_BUF_FULL, &buf->flags);
-+
-+	WRITE_ONCE(buf->wpos, wpos);
-+	return rpos == wpos;
-+}
-+
-+static void sbefifo_free(struct kref *kref)
-+{
-+	struct sbefifo *sbefifo;
-+
-+	sbefifo = container_of(kref, struct sbefifo, kref);
-+	kfree(sbefifo);
-+}
-+
-+static void sbefifo_get(struct sbefifo *sbefifo)
-+{
-+	kref_get(&sbefifo->kref);
-+}
-+
-+static void sbefifo_put(struct sbefifo *sbefifo)
-+{
-+	kref_put(&sbefifo->kref, sbefifo_free);
-+}
-+
-+static struct sbefifo_xfr *sbefifo_enq_xfr(struct sbefifo_client *client)
-+{
-+	struct sbefifo *sbefifo = client->dev;
-+	struct sbefifo_xfr *xfr;
-+
-+	xfr = kzalloc(sizeof(*xfr), GFP_KERNEL);
-+	if (!xfr)
-+		return NULL;
-+
-+	xfr->rbuf = &client->rbuf;
-+	xfr->wbuf = &client->wbuf;
-+	list_add_tail(&xfr->xfrs, &sbefifo->xfrs);
-+	list_add_tail(&xfr->client, &client->xfrs);
-+
-+	return xfr;
-+}
-+
-+static struct sbefifo_xfr *sbefifo_client_next_xfr(
-+		struct sbefifo_client *client)
-+{
-+	if (list_empty(&client->xfrs))
-+		return NULL;
-+
-+	return container_of(client->xfrs.next, struct sbefifo_xfr,
-+			client);
-+}
-+
-+static bool sbefifo_xfr_rsp_pending(struct sbefifo_client *client)
-+{
-+	struct sbefifo_xfr *xfr;
-+
-+	xfr = sbefifo_client_next_xfr(client);
-+	if (xfr && test_bit(SBEFIFO_XFR_RESP_PENDING, &xfr->flags))
-+		return true;
-+
-+	return false;
-+}
-+
-+static struct sbefifo_client *sbefifo_new_client(struct sbefifo *sbefifo)
-+{
-+	struct sbefifo_client *client;
-+
-+	client = kzalloc(sizeof(*client), GFP_KERNEL);
-+	if (!client)
-+		return NULL;
-+
-+	kref_init(&client->kref);
-+	client->dev = sbefifo;
-+	sbefifo_buf_init(&client->rbuf);
-+	sbefifo_buf_init(&client->wbuf);
-+	INIT_LIST_HEAD(&client->xfrs);
-+
-+	sbefifo_get(sbefifo);
-+
-+	return client;
-+}
-+
-+static void sbefifo_client_release(struct kref *kref)
-+{
-+	struct sbefifo_client *client;
-+	struct sbefifo_xfr *xfr;
-+
-+	client = container_of(kref, struct sbefifo_client, kref);
-+	list_for_each_entry(xfr, &client->xfrs, client) {
-+		/*
-+		 * The client left with pending or running xfrs.
-+		 * Cancel them.
-+		 */
-+		set_bit(SBEFIFO_XFR_CANCEL, &xfr->flags);
-+		sbefifo_get(client->dev);
-+		if (mod_timer(&client->dev->poll_timer, jiffies))
-+			sbefifo_put(client->dev);
-+	}
-+
-+	sbefifo_put(client->dev);
-+	kfree(client);
-+}
-+
-+static void sbefifo_get_client(struct sbefifo_client *client)
-+{
-+	kref_get(&client->kref);
-+}
-+
-+static void sbefifo_put_client(struct sbefifo_client *client)
-+{
-+	kref_put(&client->kref, sbefifo_client_release);
-+}
-+
-+static struct sbefifo_xfr *sbefifo_next_xfr(struct sbefifo *sbefifo)
-+{
-+	struct sbefifo_xfr *xfr, *tmp;
-+
-+	list_for_each_entry_safe(xfr, tmp, &sbefifo->xfrs, xfrs) {
-+		if (unlikely(test_bit(SBEFIFO_XFR_CANCEL, &xfr->flags))) {
-+			/* Discard cancelled transfers. */
-+			list_del(&xfr->xfrs);
-+			kfree(xfr);
-+			continue;
-+		}
-+		return xfr;
-+	}
-+
-+	return NULL;
-+}
-+
-+static void sbefifo_poll_timer(unsigned long data)
-+{
-+	static const unsigned long EOT_MASK = 0x000000ff;
-+	struct sbefifo *sbefifo = (void *)data;
-+	struct sbefifo_buf *rbuf, *wbuf;
-+	struct sbefifo_xfr *xfr = NULL;
-+	struct sbefifo_buf drain;
-+	size_t devn, bufn;
-+	int eot = 0;
-+	int ret = 0;
-+	u32 sts;
-+	int i;
-+
-+	spin_lock(&sbefifo->lock);
-+	xfr = list_first_entry_or_null(&sbefifo->xfrs, struct sbefifo_xfr,
-+			xfrs);
-+	if (!xfr)
-+		goto out_unlock;
-+
-+	rbuf = xfr->rbuf;
-+	wbuf = xfr->wbuf;
-+
-+	if (unlikely(test_bit(SBEFIFO_XFR_CANCEL, &xfr->flags))) {
-+		/* The client left. */
-+		rbuf = &drain;
-+		wbuf = &drain;
-+		sbefifo_buf_init(&drain);
-+		if (!test_bit(SBEFIFO_XFR_RESP_PENDING, &xfr->flags))
-+			set_bit(SBEFIFO_XFR_WRITE_DONE, &xfr->flags);
-+	}
-+
-+	 /* Drain the write buffer. */
-+	while ((bufn = sbefifo_buf_nbreadable(wbuf))) {
-+		ret = sbefifo_inw(sbefifo, SBEFIFO_UP | SBEFIFO_STS,
-+				&sts);
-+		if (ret)
-+			goto out;
-+
-+		devn = sbefifo_dev_nwwriteable(sts);
-+		if (devn == 0) {
-+			/* No open slot for write.  Reschedule. */
-+			sbefifo->poll_timer.expires = jiffies +
-+				msecs_to_jiffies(500);
-+			add_timer(&sbefifo->poll_timer);
-+			goto out_unlock;
-+		}
-+
-+		devn = min_t(size_t, devn, bufn >> 2);
-+		for (i = 0; i < devn; i++) {
-+			ret = sbefifo_writew(sbefifo, *wbuf->rpos);
-+			if (ret)
-+				goto out;
-+
-+			sbefifo_buf_readnb(wbuf, 1 << 2);
-+		}
-+	}
-+
-+	 /* Send EOT if the writer is finished. */
-+	if (test_and_clear_bit(SBEFIFO_XFR_WRITE_DONE, &xfr->flags)) {
-+		ret = sbefifo_outw(sbefifo,
-+				SBEFIFO_UP | SBEFIFO_EOT_RAISE,
-+				SBEFIFO_EOT_MAGIC);
-+		if (ret)
-+			goto out;
-+
-+		/* Inform reschedules that the writer is finished. */
-+		set_bit(SBEFIFO_XFR_RESP_PENDING, &xfr->flags);
-+	}
-+
-+	/* Nothing left to do if the writer is not finished. */
-+	if (!test_bit(SBEFIFO_XFR_RESP_PENDING, &xfr->flags))
-+		goto out;
-+
-+	 /* Fill the read buffer. */
-+	while ((bufn = sbefifo_buf_nbwriteable(rbuf))) {
-+		ret = sbefifo_inw(sbefifo, SBEFIFO_DWN | SBEFIFO_STS, &sts);
-+		if (ret)
-+			goto out;
-+
-+		devn = sbefifo_dev_nwreadable(sts);
-+		if (devn == 0) {
-+			/* No data yet.  Reschedule. */
-+			sbefifo->poll_timer.expires = jiffies +
-+				msecs_to_jiffies(500);
-+			add_timer(&sbefifo->poll_timer);
-+			goto out_unlock;
-+		}
-+
-+		/* Fill.  The EOT word is discarded.  */
-+		devn = min_t(size_t, devn, bufn >> 2);
-+		eot = (sts & EOT_MASK) != 0;
-+		if (eot)
-+			devn--;
-+
-+		for (i = 0; i < devn; i++) {
-+			ret = sbefifo_readw(sbefifo, rbuf->wpos);
-+			if (ret)
-+				goto out;
-+
-+			if (likely(!test_bit(SBEFIFO_XFR_CANCEL, &xfr->flags)))
-+				sbefifo_buf_wrotenb(rbuf, 1 << 2);
-+		}
-+
-+		if (eot) {
-+			ret = sbefifo_ack_eot(sbefifo);
-+			if (ret)
-+				goto out;
-+
-+			set_bit(SBEFIFO_XFR_COMPLETE, &xfr->flags);
-+			list_del(&xfr->xfrs);
-+			if (unlikely(test_bit(SBEFIFO_XFR_CANCEL,
-+							&xfr->flags)))
-+				kfree(xfr);
-+			break;
-+		}
-+	}
-+
-+out:
-+	if (unlikely(ret)) {
-+		sbefifo->rc = ret;
-+		dev_err(&sbefifo->fsi_dev->dev,
-+				"Fatal bus access failure: %d\n", ret);
-+		list_for_each_entry(xfr, &sbefifo->xfrs, xfrs)
-+			kfree(xfr);
-+		INIT_LIST_HEAD(&sbefifo->xfrs);
-+
-+	} else if (eot && sbefifo_next_xfr(sbefifo)) {
-+		sbefifo_get(sbefifo);
-+		sbefifo->poll_timer.expires = jiffies;
-+		add_timer(&sbefifo->poll_timer);
-+	}
-+
-+	sbefifo_put(sbefifo);
-+	wake_up(&sbefifo->wait);
-+
-+out_unlock:
-+	spin_unlock(&sbefifo->lock);
-+}
-+
-+static int sbefifo_open(struct inode *inode, struct file *file)
-+{
-+	struct sbefifo *sbefifo = container_of(file->private_data,
-+			struct sbefifo, mdev);
-+	struct sbefifo_client *client;
-+	int ret;
-+
-+	ret = READ_ONCE(sbefifo->rc);
-+	if (ret)
-+		return ret;
-+
-+	client = sbefifo_new_client(sbefifo);
-+	if (!client)
-+		return -ENOMEM;
-+
-+	file->private_data = client;
-+
-+	return 0;
-+}
-+
-+static unsigned int sbefifo_poll(struct file *file, poll_table *wait)
-+{
-+	struct sbefifo_client *client = file->private_data;
-+	struct sbefifo *sbefifo = client->dev;
-+	unsigned int mask = 0;
-+
-+	poll_wait(file, &sbefifo->wait, wait);
-+
-+	if (READ_ONCE(sbefifo->rc))
-+		mask |= POLLERR;
-+
-+	if (sbefifo_buf_nbreadable(&client->rbuf))
-+		mask |= POLLIN;
-+
-+	if (sbefifo_buf_nbwriteable(&client->wbuf))
-+		mask |= POLLOUT;
-+
-+	return mask;
-+}
-+
-+static ssize_t sbefifo_read(struct file *file, char __user *buf,
-+		size_t len, loff_t *offset)
-+{
-+	struct sbefifo_client *client = file->private_data;
-+	struct sbefifo *sbefifo = client->dev;
-+	struct sbefifo_xfr *xfr;
-+	ssize_t ret = 0;
-+	size_t n;
-+
-+	WARN_ON(*offset);
-+
-+	if (!access_ok(VERIFY_WRITE, buf, len))
-+		return -EFAULT;
-+
-+	if ((len >> 2) << 2 != len)
-+		return -EINVAL;
-+
-+	if ((file->f_flags & O_NONBLOCK) && !sbefifo_xfr_rsp_pending(client))
-+		return -EAGAIN;
-+
-+	sbefifo_get_client(client);
-+	if (wait_event_interruptible(sbefifo->wait,
-+				(ret = READ_ONCE(sbefifo->rc)) ||
-+				(n = sbefifo_buf_nbreadable(
-+						&client->rbuf)))) {
-+		sbefifo_put_client(client);
-+		return -ERESTARTSYS;
-+	}
-+	if (ret) {
-+		INIT_LIST_HEAD(&client->xfrs);
-+		sbefifo_put_client(client);
-+		return ret;
-+	}
-+
-+	n = min_t(size_t, n, len);
-+
-+	if (copy_to_user(buf, READ_ONCE(client->rbuf.rpos), n)) {
-+		sbefifo_put_client(client);
-+		return -EFAULT;
-+	}
-+
-+	if (sbefifo_buf_readnb(&client->rbuf, n)) {
-+		xfr = sbefifo_client_next_xfr(client);
-+		if (!test_bit(SBEFIFO_XFR_COMPLETE, &xfr->flags)) {
-+			/*
-+			 * Fill the read buffer back up.
-+			 */
-+			sbefifo_get(sbefifo);
-+			if (mod_timer(&client->dev->poll_timer, jiffies))
-+				sbefifo_put(sbefifo);
-+		} else {
-+			kfree(xfr);
-+			list_del(&xfr->client);
-+			wake_up(&sbefifo->wait);
-+		}
-+	}
-+
-+	sbefifo_put_client(client);
-+
-+	return n;
-+}
-+
-+static ssize_t sbefifo_write(struct file *file, const char __user *buf,
-+		size_t len, loff_t *offset)
-+{
-+	struct sbefifo_client *client = file->private_data;
-+	struct sbefifo *sbefifo = client->dev;
-+	struct sbefifo_xfr *xfr;
-+	ssize_t ret = 0;
-+	size_t n;
-+
-+	WARN_ON(*offset);
-+
-+	if (!access_ok(VERIFY_READ, buf, len))
-+		return -EFAULT;
-+
-+	if ((len >> 2) << 2 != len)
-+		return -EINVAL;
-+
-+	if (!len)
-+		return 0;
-+
-+	n = sbefifo_buf_nbwriteable(&client->wbuf);
-+
-+	spin_lock_irq(&sbefifo->lock);
-+	xfr = sbefifo_next_xfr(sbefifo);
-+
-+	if ((file->f_flags & O_NONBLOCK) && xfr && n < len) {
-+		spin_unlock_irq(&sbefifo->lock);
-+		return -EAGAIN;
-+	}
-+
-+	xfr = sbefifo_enq_xfr(client);
-+	if (!xfr) {
-+		spin_unlock_irq(&sbefifo->lock);
-+		return -ENOMEM;
-+	}
-+	spin_unlock_irq(&sbefifo->lock);
-+
-+	sbefifo_get_client(client);
-+
-+	/*
-+	 * Partial writes are not really allowed in that EOT is sent exactly
-+	 * once per write.
-+	 */
-+	while (len) {
-+		if (wait_event_interruptible(sbefifo->wait,
-+				READ_ONCE(sbefifo->rc) ||
-+					(sbefifo_client_next_xfr(client) == xfr &&
-+					 (n = sbefifo_buf_nbwriteable(
-+							&client->wbuf))))) {
-+			set_bit(SBEFIFO_XFR_CANCEL, &xfr->flags);
-+			sbefifo_get(sbefifo);
-+			if (mod_timer(&sbefifo->poll_timer, jiffies))
-+				sbefifo_put(sbefifo);
-+
-+			sbefifo_put_client(client);
-+			return -ERESTARTSYS;
-+		}
-+		if (sbefifo->rc) {
-+			INIT_LIST_HEAD(&client->xfrs);
-+			sbefifo_put_client(client);
-+			return sbefifo->rc;
-+		}
-+
-+		n = min_t(size_t, n, len);
-+
-+		if (copy_from_user(READ_ONCE(client->wbuf.wpos), buf, n)) {
-+			set_bit(SBEFIFO_XFR_CANCEL, &xfr->flags);
-+			sbefifo_get(sbefifo);
-+			if (mod_timer(&sbefifo->poll_timer, jiffies))
-+				sbefifo_put(sbefifo);
-+			sbefifo_put_client(client);
-+			return -EFAULT;
-+		}
-+
-+		sbefifo_buf_wrotenb(&client->wbuf, n);
-+		len -= n;
-+		buf += n;
-+		ret += n;
-+
-+		/*
-+		 * Drain the write buffer.
-+		 */
-+		sbefifo_get(sbefifo);
-+		if (mod_timer(&client->dev->poll_timer, jiffies))
-+			sbefifo_put(sbefifo);
-+	}
-+
-+	set_bit(SBEFIFO_XFR_WRITE_DONE, &xfr->flags);
-+	sbefifo_put_client(client);
-+
-+	return ret;
-+}
-+
-+static int sbefifo_release(struct inode *inode, struct file *file)
-+{
-+	struct sbefifo_client *client = file->private_data;
-+	struct sbefifo *sbefifo = client->dev;
-+
-+	sbefifo_put_client(client);
-+
-+	return READ_ONCE(sbefifo->rc);
-+}
-+
-+static const struct file_operations sbefifo_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= sbefifo_open,
-+	.read		= sbefifo_read,
-+	.write		= sbefifo_write,
-+	.poll		= sbefifo_poll,
-+	.release	= sbefifo_release,
-+};
-+
-+static int sbefifo_probe(struct device *dev)
-+{
-+	struct fsi_device *fsi_dev = to_fsi_dev(dev);
-+	struct sbefifo *sbefifo;
-+	u32 sts;
-+	int ret;
-+
-+	dev_info(dev, "Found sbefifo device\n");
-+	sbefifo = kzalloc(sizeof(*sbefifo), GFP_KERNEL);
-+	if (!sbefifo)
-+		return -ENOMEM;
-+
-+	sbefifo->fsi_dev = fsi_dev;
-+
-+	ret = sbefifo_inw(sbefifo,
-+			SBEFIFO_UP | SBEFIFO_STS, &sts);
-+	if (ret)
-+		return ret;
-+	if (!(sts & SBEFIFO_EMPTY)) {
-+		dev_err(&sbefifo->fsi_dev->dev,
-+				"Found data in upstream fifo\n");
-+		return -EIO;
-+	}
-+
-+	ret = sbefifo_inw(sbefifo, SBEFIFO_DWN | SBEFIFO_STS, &sts);
-+	if (ret)
-+		return ret;
-+	if (!(sts & SBEFIFO_EMPTY)) {
-+		dev_err(&sbefifo->fsi_dev->dev,
-+				"Found data in downstream fifo\n");
-+		return -EIO;
-+	}
-+
-+	sbefifo->mdev.minor = MISC_DYNAMIC_MINOR;
-+	sbefifo->mdev.fops = &sbefifo_fops;
-+	sbefifo->mdev.name = sbefifo->name;
-+	sbefifo->mdev.parent = dev;
-+	spin_lock_init(&sbefifo->lock);
-+	kref_init(&sbefifo->kref);
-+
-+	sbefifo->idx = ida_simple_get(&sbefifo_ida, 1, INT_MAX, GFP_KERNEL);
-+	snprintf(sbefifo->name, sizeof(sbefifo->name), "sbefifo%d",
-+			sbefifo->idx);
-+	init_waitqueue_head(&sbefifo->wait);
-+	INIT_LIST_HEAD(&sbefifo->xfrs);
-+
-+	/* This bit of silicon doesn't offer any interrupts... */
-+	setup_timer(&sbefifo->poll_timer, sbefifo_poll_timer,
-+			(unsigned long)sbefifo);
-+
-+	list_add(&sbefifo->link, &sbefifo_fifos);
-+	return misc_register(&sbefifo->mdev);
-+}
-+
-+static int sbefifo_remove(struct device *dev)
-+{
-+	struct fsi_device *fsi_dev = to_fsi_dev(dev);
-+	struct sbefifo *sbefifo, *sbefifo_tmp;
-+	struct sbefifo_xfr *xfr;
-+
-+	list_for_each_entry_safe(sbefifo, sbefifo_tmp, &sbefifo_fifos, link) {
-+		if (sbefifo->fsi_dev != fsi_dev)
-+			continue;
-+		misc_deregister(&sbefifo->mdev);
-+		list_del(&sbefifo->link);
-+		ida_simple_remove(&sbefifo_ida, sbefifo->idx);
-+
-+		if (del_timer_sync(&sbefifo->poll_timer))
-+			sbefifo_put(sbefifo);
-+
-+		spin_lock(&sbefifo->lock);
-+		list_for_each_entry(xfr, &sbefifo->xfrs, xfrs)
-+			kfree(xfr);
-+		spin_unlock(&sbefifo->lock);
-+
-+		WRITE_ONCE(sbefifo->rc, -ENODEV);
-+
-+		wake_up(&sbefifo->wait);
-+		sbefifo_put(sbefifo);
-+	}
-+
-+	return 0;
-+}
-+
-+static struct fsi_device_id sbefifo_ids[] = {
-+	{
-+		.engine_type = FSI_ENGID_SBE,
-+		.version = FSI_VERSION_ANY,
-+	},
-+	{ 0 }
-+};
-+
-+static struct fsi_driver sbefifo_drv = {
-+	.id_table = sbefifo_ids,
-+	.drv = {
-+		.name = DEVICE_NAME,
-+		.bus = &fsi_bus_type,
-+		.probe = sbefifo_probe,
-+		.remove = sbefifo_remove,
-+	}
-+};
-+
-+static int sbefifo_init(void)
-+{
-+	INIT_LIST_HEAD(&sbefifo_fifos);
-+	return fsi_driver_register(&sbefifo_drv);
-+}
-+
-+static void sbefifo_exit(void)
-+{
-+	fsi_driver_unregister(&sbefifo_drv);
-+}
-+
-+module_init(sbefifo_init);
-+module_exit(sbefifo_exit);
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Brad Bishop <bradleyb@fuzziesquirrel.com>");
-+MODULE_DESCRIPTION("Linux device interface to the POWER self boot engine");
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-1-6-drivers-i2c-Add-FSI-attached-I2C-master-algorithm.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-1-6-drivers-i2c-Add-FSI-attached-I2C-master-algorithm.patch
deleted file mode 100644
index f38a6a4..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-1-6-drivers-i2c-Add-FSI-attached-I2C-master-algorithm.patch
+++ /dev/null
@@ -1,326 +0,0 @@
-From patchwork Wed May 10 15:52:37 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux, dev-4.10, v2,
- 1/6] drivers: i2c: Add FSI-attached I2C master algorithm
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 760697
-Message-Id: <1494431562-25101-2-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, cbostic@linux.vnet.ibm.com
-Date: Wed, 10 May 2017 10:52:37 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-Initial startup code for the I2C algorithm to drive the I2C master
-located on POWER CPUs over FSI bus.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/Makefile             |   2 +-
- drivers/i2c/busses/Kconfig   |  11 ++
- drivers/i2c/busses/Makefile  |   1 +
- drivers/i2c/busses/i2c-fsi.c | 245 +++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 258 insertions(+), 1 deletion(-)
- create mode 100644 drivers/i2c/busses/i2c-fsi.c
-
-diff --git a/drivers/Makefile b/drivers/Makefile
-index 67ce51d..278f109 100644
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -105,6 +105,7 @@ obj-$(CONFIG_SERIO)		+= input/serio/
- obj-$(CONFIG_GAMEPORT)		+= input/gameport/
- obj-$(CONFIG_INPUT)		+= input/
- obj-$(CONFIG_RTC_LIB)		+= rtc/
-+obj-$(CONFIG_FSI)		+= fsi/
- obj-y				+= i2c/ media/
- obj-$(CONFIG_PPS)		+= pps/
- obj-y				+= ptp/
-@@ -173,4 +174,3 @@ obj-$(CONFIG_STM)		+= hwtracing/stm/
- obj-$(CONFIG_ANDROID)		+= android/
- obj-$(CONFIG_NVMEM)		+= nvmem/
- obj-$(CONFIG_FPGA)		+= fpga/
--obj-$(CONFIG_FSI)		+= fsi/
-diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
-index 7e34901d..0c714e0 100644
---- a/drivers/i2c/busses/Kconfig
-+++ b/drivers/i2c/busses/Kconfig
-@@ -1245,4 +1245,15 @@ config I2C_OPAL
- 	  This driver can also be built as a module. If so, the module will be
- 	  called as i2c-opal.
- 
-+config I2C_FSI
-+	tristate "FSI I2C driver"
-+	depends on FSI
-+	help
-+	  Driver for FSI bus attached I2C masters. These are I2C masters that
-+	  are connected to the system over a FSI bus, instead of the more
-+	  common PCI or MMIO interface.
-+
-+	  This driver can also be built as a module. If so, the module will be
-+	  called as i2c-fsi.
-+
- endmenu
-diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
-index 5798b4e..547773b 100644
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -124,5 +124,6 @@ obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
- obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
- obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
- obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
-+obj-$(CONFIG_I2C_FSI)		+= i2c-fsi.o
- 
- ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
-diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
-new file mode 100644
-index 0000000..3c1087d
---- /dev/null
-+++ b/drivers/i2c/busses/i2c-fsi.c
-@@ -0,0 +1,245 @@
-+/*
-+ * Copyright 2017 IBM Corporation
-+ *
-+ * Eddie James <eajames@us.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.
-+ */
-+
-+#include <linux/fsi.h>
-+#include <linux/i2c.h>
-+#include <linux/jiffies.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/sched.h>
-+#include <linux/semaphore.h>
-+#include <linux/wait.h>
-+
-+#define FSI_ENGID_I2C_FSI	0x7
-+
-+/* Find left shift from first set bit in m */
-+#define MASK_TO_LSH(m)		(__builtin_ffsll(m) - 1ULL)
-+
-+/* Extract field m from v */
-+#define GETFIELD(m, v)		(((v) & (m)) >> MASK_TO_LSH(m))
-+
-+/* Set field m of v to val */
-+#define SETFIELD(m, v, val)	\
-+	(((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
-+
-+#define I2C_DEFAULT_CLK_DIV	6
-+
-+/* i2c registers */
-+#define I2C_FSI_FIFO		0x00
-+#define I2C_FSI_CMD		0x04
-+#define I2C_FSI_MODE		0x08
-+#define I2C_FSI_WATER_MARK	0x0C
-+#define I2C_FSI_INT_MASK	0x10
-+#define I2C_FSI_INT_COND	0x14
-+#define I2C_FSI_OR_INT_MASK	0x14
-+#define I2C_FSI_INTS		0x18
-+#define I2C_FSI_AND_INT_MASK	0x18
-+#define I2C_FSI_STAT		0x1C
-+#define I2C_FSI_RESET_I2C	0x1C
-+#define I2C_FSI_ESTAT		0x20
-+#define I2C_FSI_RESET_ERR	0x20
-+#define I2C_FSI_RESID_LEN	0x24
-+#define I2C_FSI_SET_SCL		0x24
-+#define I2C_FSI_PORT_BUSY	0x28
-+#define I2C_FSI_RESET_SCL	0x2C
-+#define I2C_FSI_SET_SDA		0x30
-+#define I2C_FSI_RESET_SDA	0x34
-+
-+/* cmd register */
-+#define I2C_CMD_WITH_START	0x80000000
-+#define I2C_CMD_WITH_ADDR	0x40000000
-+#define I2C_CMD_RD_CONT		0x20000000
-+#define I2C_CMD_WITH_STOP	0x10000000
-+#define I2C_CMD_FORCELAUNCH	0x08000000
-+#define I2C_CMD_ADDR		0x00fe0000
-+#define I2C_CMD_READ		0x00010000
-+#define I2C_CMD_LEN		0x0000ffff
-+
-+/* mode register */
-+#define I2C_MODE_CLKDIV		0xffff0000
-+#define I2C_MODE_PORT		0x0000fc00
-+#define I2C_MODE_ENHANCED	0x00000008
-+#define I2C_MODE_DIAG		0x00000004
-+#define I2C_MODE_PACE_ALLOW	0x00000002
-+#define I2C_MODE_WRAP		0x00000001
-+
-+/* watermark register */
-+#define I2C_WATERMARK_HI	0x0000f000
-+#define I2C_WATERMARK_LO	0x000000f0
-+
-+#define I2C_FIFO_HI_LVL		4
-+#define I2C_FIFO_LO_LVL		4
-+
-+/* interrupt register */
-+#define I2C_INT_INV_CMD		0x00008000
-+#define I2C_INT_PARITY		0x00004000
-+#define I2C_INT_BE_OVERRUN	0x00002000
-+#define I2C_INT_BE_ACCESS	0x00001000
-+#define I2C_INT_LOST_ARB	0x00000800
-+#define I2C_INT_NACK		0x00000400
-+#define I2C_INT_DAT_REQ		0x00000200
-+#define I2C_INT_CMD_COMP	0x00000100
-+#define I2C_INT_STOP_ERR	0x00000080
-+#define I2C_INT_BUSY		0x00000040
-+#define I2C_INT_IDLE		0x00000020
-+
-+#define I2C_INT_ENABLE		0x0000ff80
-+#define I2C_INT_ERR		0x0000fcc0
-+
-+/* status register */
-+#define I2C_STAT_INV_CMD	0x80000000
-+#define I2C_STAT_PARITY		0x40000000
-+#define I2C_STAT_BE_OVERRUN	0x20000000
-+#define I2C_STAT_BE_ACCESS	0x10000000
-+#define I2C_STAT_LOST_ARB	0x08000000
-+#define I2C_STAT_NACK		0x04000000
-+#define I2C_STAT_DAT_REQ	0x02000000
-+#define I2C_STAT_CMD_COMP	0x01000000
-+#define I2C_STAT_STOP_ERR	0x00800000
-+#define I2C_STAT_MAX_PORT	0x000f0000
-+#define I2C_STAT_ANY_INT	0x00008000
-+#define I2C_STAT_SCL_IN		0x00000800
-+#define I2C_STAT_SDA_IN		0x00000400
-+#define I2C_STAT_PORT_BUSY	0x00000200
-+#define I2C_STAT_SELF_BUSY	0x00000100
-+#define I2C_STAT_FIFO_COUNT	0x000000ff
-+
-+#define I2C_STAT_ERR		0xfc800000
-+#define I2C_STAT_ANY_RESP	0xff800000
-+
-+/* extended status register */
-+#define I2C_ESTAT_FIFO_SZ	0xff000000
-+#define I2C_ESTAT_SCL_IN_SY	0x00008000
-+#define I2C_ESTAT_SDA_IN_SY	0x00004000
-+#define I2C_ESTAT_S_SCL		0x00002000
-+#define I2C_ESTAT_S_SDA		0x00001000
-+#define I2C_ESTAT_M_SCL		0x00000800
-+#define I2C_ESTAT_M_SDA		0x00000400
-+#define I2C_ESTAT_HI_WATER	0x00000200
-+#define I2C_ESTAT_LO_WATER	0x00000100
-+#define I2C_ESTAT_PORT_BUSY	0x00000080
-+#define I2C_ESTAT_SELF_BUSY	0x00000040
-+#define I2C_ESTAT_VERSION	0x0000001f
-+
-+struct fsi_i2c_master {
-+	struct fsi_device	*fsi;
-+	u8			fifo_size;
-+};
-+
-+static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg,
-+			    u32 *data)
-+{
-+	int rc;
-+	u32 raw_data;
-+
-+	rc = fsi_device_read(fsi, reg, &raw_data, sizeof(raw_data));
-+	if (rc)
-+		return rc;
-+
-+	*data = be32_to_cpu(raw_data);
-+
-+	return 0;
-+}
-+
-+static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg,
-+			     u32 *data)
-+{
-+	u32 raw_data = cpu_to_be32(*data);
-+
-+	return fsi_device_write(fsi, reg, &raw_data, sizeof(raw_data));
-+}
-+
-+static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c)
-+{
-+	int rc;
-+	u32 mode = I2C_MODE_ENHANCED, extended_status, watermark = 0;
-+	u32 interrupt = 0;
-+
-+	/* since we use polling, disable interrupts */
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_INT_MASK, &interrupt);
-+	if (rc)
-+		return rc;
-+
-+	mode = SETFIELD(I2C_MODE_CLKDIV, mode, I2C_DEFAULT_CLK_DIV);
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
-+	if (rc)
-+		return rc;
-+
-+	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_ESTAT, &extended_status);
-+	if (rc)
-+		return rc;
-+
-+	i2c->fifo_size = GETFIELD(I2C_ESTAT_FIFO_SZ, extended_status);
-+	watermark = SETFIELD(I2C_WATERMARK_HI, watermark,
-+			     i2c->fifo_size - I2C_FIFO_HI_LVL);
-+	watermark = SETFIELD(I2C_WATERMARK_LO, watermark,
-+			     I2C_FIFO_LO_LVL);
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_WATER_MARK, &watermark);
-+
-+	return rc;
-+}
-+
-+static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
-+			int num)
-+{
-+	return -ENOSYS;
-+}
-+
-+static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
-+{
-+	return I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_10BIT_ADDR;
-+}
-+
-+static const struct i2c_algorithm fsi_i2c_algorithm = {
-+	.master_xfer = fsi_i2c_xfer,
-+	.functionality = fsi_i2c_functionality,
-+};
-+
-+static int fsi_i2c_probe(struct device *dev)
-+{
-+	struct fsi_i2c_master *i2c;
-+	int rc;
-+
-+	i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
-+	if (!i2c)
-+		return -ENOMEM;
-+
-+	i2c->fsi = to_fsi_dev(dev);
-+
-+	rc = fsi_i2c_dev_init(i2c);
-+	if (rc)
-+		return rc;
-+
-+	dev_set_drvdata(dev, i2c);
-+
-+	return 0;
-+}
-+
-+static const struct fsi_device_id fsi_i2c_ids[] = {
-+	{ FSI_ENGID_I2C_FSI, FSI_VERSION_ANY },
-+	{ 0 }
-+};
-+
-+static struct fsi_driver fsi_i2c_driver = {
-+	.id_table = fsi_i2c_ids,
-+	.drv = {
-+		.name = "i2c_master_fsi",
-+		.bus = &fsi_bus_type,
-+		.probe = fsi_i2c_probe,
-+	},
-+};
-+
-+module_fsi_driver(fsi_i2c_driver);
-+
-+MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>");
-+MODULE_DESCRIPTION("FSI attached I2C master");
-+MODULE_LICENSE("GPL");
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-2-6-drivers-i2c-Add-port-structure-to-FSI-algorithm.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-2-6-drivers-i2c-Add-port-structure-to-FSI-algorithm.patch
deleted file mode 100644
index 20f66bf..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-2-6-drivers-i2c-Add-port-structure-to-FSI-algorithm.patch
+++ /dev/null
@@ -1,194 +0,0 @@
-From patchwork Wed May 10 15:52:38 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux, dev-4.10, v2,
- 2/6] drivers: i2c: Add port structure to FSI algorithm
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 760696
-Message-Id: <1494431562-25101-3-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, cbostic@linux.vnet.ibm.com
-Date: Wed, 10 May 2017 10:52:38 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-Add and initialize I2C adapters for each port on the FSI-attached I2C
-master. Ports are defined in the devicetree.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/i2c/busses/i2c-fsi.c | 113 ++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 112 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
-index 3c1087d..cdebc99 100644
---- a/drivers/i2c/busses/i2c-fsi.c
-+++ b/drivers/i2c/busses/i2c-fsi.c
-@@ -30,6 +30,7 @@
- #define SETFIELD(m, v, val)	\
- 	(((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
- 
-+#define I2C_MASTER_NR_OFFSET	100
- #define I2C_DEFAULT_CLK_DIV	6
- 
- /* i2c registers */
-@@ -131,9 +132,21 @@
- 
- struct fsi_i2c_master {
- 	struct fsi_device	*fsi;
-+	int			idx;
- 	u8			fifo_size;
-+	struct list_head	ports;
-+	struct ida		ida;
- };
- 
-+struct fsi_i2c_port {
-+	struct list_head	list;
-+	struct i2c_adapter	adapter;
-+	struct fsi_i2c_master	*master;
-+	u16			port;
-+};
-+
-+static DEFINE_IDA(fsi_i2c_ida);
-+
- static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg,
- 			    u32 *data)
- {
-@@ -188,9 +201,44 @@ static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c)
- 	return rc;
- }
- 
-+static int fsi_i2c_set_port(struct fsi_i2c_port *port)
-+{
-+	int rc;
-+	struct fsi_device *fsi = port->master->fsi;
-+	u32 mode, dummy = 0;
-+	u16 old_port;
-+
-+	rc = fsi_i2c_read_reg(fsi, I2C_FSI_MODE, &mode);
-+	if (rc)
-+		return rc;
-+
-+	old_port = GETFIELD(I2C_MODE_PORT, mode);
-+
-+	if (old_port != port->port) {
-+		mode = SETFIELD(I2C_MODE_PORT, mode, port->port);
-+		rc = fsi_i2c_write_reg(fsi, I2C_FSI_MODE, &mode);
-+		if (rc)
-+			return rc;
-+
-+		/* reset engine when port is changed */
-+		rc = fsi_i2c_write_reg(fsi, I2C_FSI_RESET_ERR, &dummy);
-+		if (rc)
-+			return rc;
-+	}
-+
-+	return rc;
-+}
-+
- static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- 			int num)
- {
-+	int rc;
-+	struct fsi_i2c_port *port = adap->algo_data;
-+
-+	rc = fsi_i2c_set_port(port);
-+	if (rc)
-+		return rc;
-+
- 	return -ENOSYS;
- }
- 
-@@ -207,13 +255,59 @@ static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
- static int fsi_i2c_probe(struct device *dev)
- {
- 	struct fsi_i2c_master *i2c;
--	int rc;
-+	struct fsi_i2c_port *port;
-+	struct device_node *np;
-+	int rc, idx;
-+	u32 port_no;
- 
- 	i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
- 	if (!i2c)
- 		return -ENOMEM;
- 
- 	i2c->fsi = to_fsi_dev(dev);
-+	i2c->idx = ida_simple_get(&fsi_i2c_ida, 1, INT_MAX, GFP_KERNEL);
-+	ida_init(&i2c->ida);
-+	INIT_LIST_HEAD(&i2c->ports);
-+
-+	if (dev->of_node) {
-+		/* add adapter for each i2c port of the master */
-+		for_each_child_of_node(dev->of_node, np) {
-+			rc = of_property_read_u32(np, "port", &port_no);
-+			if (rc || port_no > 0xFFFF)
-+				continue;
-+
-+			/* make sure we don't overlap index with a buggy dts */
-+			idx = ida_simple_get(&i2c->ida, port_no,
-+					     port_no + 1, GFP_KERNEL);
-+			if (idx < 0)
-+				continue;
-+
-+			port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
-+			if (!port)
-+				return -ENOMEM;
-+
-+			port->master = i2c;
-+			port->port = (u16)port_no;
-+
-+			port->adapter.owner = THIS_MODULE;
-+			port->adapter.dev.parent = dev;
-+			port->adapter.algo = &fsi_i2c_algorithm;
-+			port->adapter.algo_data = port;
-+			/* number ports uniquely */
-+			port->adapter.nr = (i2c->idx * I2C_MASTER_NR_OFFSET) +
-+				port_no;
-+
-+			snprintf(port->adapter.name,
-+				 sizeof(port->adapter.name),
-+				 "fsi_i2c-%u", port_no);
-+
-+			rc = i2c_add_numbered_adapter(&port->adapter);
-+			if (rc < 0)
-+				return rc;
-+
-+			list_add(&port->list, &i2c->ports);
-+		}
-+	}
- 
- 	rc = fsi_i2c_dev_init(i2c);
- 	if (rc)
-@@ -224,6 +318,22 @@ static int fsi_i2c_probe(struct device *dev)
- 	return 0;
- }
- 
-+static int fsi_i2c_remove(struct device *dev)
-+{
-+	struct fsi_i2c_master *i2c = dev_get_drvdata(dev);
-+	struct fsi_i2c_port *port;
-+
-+	list_for_each_entry(port, &i2c->ports, list) {
-+		i2c_del_adapter(&port->adapter);
-+	}
-+
-+	ida_destroy(&i2c->ida);
-+
-+	ida_simple_remove(&fsi_i2c_ida, i2c->idx);
-+
-+	return 0;
-+}
-+
- static const struct fsi_device_id fsi_i2c_ids[] = {
- 	{ FSI_ENGID_I2C_FSI, FSI_VERSION_ANY },
- 	{ 0 }
-@@ -235,6 +345,7 @@ static int fsi_i2c_probe(struct device *dev)
- 		.name = "i2c_master_fsi",
- 		.bus = &fsi_bus_type,
- 		.probe = fsi_i2c_probe,
-+		.remove = fsi_i2c_remove,
- 	},
- };
- 
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-3-6-drivers-i2c-Add-transfer-implementation-for-FSI-algorithm.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-3-6-drivers-i2c-Add-transfer-implementation-for-FSI-algorithm.patch
deleted file mode 100644
index 50410ff..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-3-6-drivers-i2c-Add-transfer-implementation-for-FSI-algorithm.patch
+++ /dev/null
@@ -1,243 +0,0 @@
-From patchwork Wed May 10 15:52:39 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux, dev-4.10, v2,
- 3/6] drivers: i2c: Add transfer implementation for FSI algorithm
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 760702
-Message-Id: <1494431562-25101-4-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, cbostic@linux.vnet.ibm.com
-Date: Wed, 10 May 2017 10:52:39 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-Execute I2C transfers from the FSI-attached I2C master. Use polling
-instead of interrupts as we have no hardware IRQ over FSI.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/i2c/busses/i2c-fsi.c | 193 ++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 191 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
-index cdebc99..f690b16 100644
---- a/drivers/i2c/busses/i2c-fsi.c
-+++ b/drivers/i2c/busses/i2c-fsi.c
-@@ -143,6 +143,7 @@ struct fsi_i2c_port {
- 	struct i2c_adapter	adapter;
- 	struct fsi_i2c_master	*master;
- 	u16			port;
-+	u16			xfrd;
- };
- 
- static DEFINE_IDA(fsi_i2c_ida);
-@@ -229,17 +230,205 @@ static int fsi_i2c_set_port(struct fsi_i2c_port *port)
- 	return rc;
- }
- 
-+static int fsi_i2c_start(struct fsi_i2c_port *port, struct i2c_msg *msg,
-+			 bool stop)
-+{
-+	int rc;
-+	struct fsi_i2c_master *i2c = port->master;
-+	u32 cmd = I2C_CMD_WITH_START | I2C_CMD_WITH_ADDR;
-+
-+	port->xfrd = 0;
-+
-+	if (msg->flags & I2C_M_RD)
-+		cmd |= I2C_CMD_READ;
-+
-+	if (stop || msg->flags & I2C_M_STOP)
-+		cmd |= I2C_CMD_WITH_STOP;
-+
-+	cmd = SETFIELD(I2C_CMD_ADDR, cmd, msg->addr >> 1);
-+	cmd = SETFIELD(I2C_CMD_LEN, cmd, msg->len);
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_CMD, &cmd);
-+
-+	return rc;
-+}
-+
-+static int fsi_i2c_write_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg,
-+			      u8 fifo_count)
-+{
-+	int write;
-+	int rc = 0;
-+	struct fsi_i2c_master *i2c = port->master;
-+	int bytes_to_write = i2c->fifo_size - fifo_count;
-+	int bytes_remaining = msg->len - port->xfrd;
-+
-+	if (bytes_to_write > bytes_remaining)
-+		bytes_to_write = bytes_remaining;
-+
-+	while (bytes_to_write > 0) {
-+		write = bytes_to_write;
-+		/* fsi limited to max 4 byte aligned ops */
-+		if (bytes_to_write > 4)
-+			write = 4;
-+		else if (write == 3)
-+			write = 2;
-+
-+		rc = fsi_device_write(i2c->fsi, I2C_FSI_FIFO,
-+				      &msg->buf[port->xfrd], write);
-+		if (rc)
-+			return rc;
-+
-+		port->xfrd += write;
-+		bytes_to_write -= write;
-+	}
-+
-+	return rc;
-+}
-+
-+static int fsi_i2c_read_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg,
-+			     u8 fifo_count)
-+{
-+	int read;
-+	int rc = 0;
-+	struct fsi_i2c_master *i2c = port->master;
-+	int xfr_remaining = msg->len - port->xfrd;
-+	u32 dummy;
-+
-+	while (fifo_count) {
-+		read = fifo_count;
-+		/* fsi limited to max 4 byte aligned ops */
-+		if (fifo_count > 4)
-+			read = 4;
-+		else if (read == 3)
-+			read = 2;
-+
-+		if (xfr_remaining) {
-+			if (xfr_remaining < read)
-+				read = xfr_remaining;
-+
-+			rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO,
-+					     &msg->buf[port->xfrd], read);
-+			if (rc)
-+				return rc;
-+
-+			port->xfrd += read;
-+			xfr_remaining -= read;
-+		} else {
-+			/* no more buffer but data in fifo, need to clear it */
-+			rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO, &dummy,
-+					     read);
-+			if (rc)
-+				return rc;
-+		}
-+
-+		fifo_count -= read;
-+	}
-+
-+	return rc;
-+}
-+
-+static int fsi_i2c_handle_status(struct fsi_i2c_port *port,
-+				 struct i2c_msg *msg, u32 status)
-+{
-+	int rc;
-+	u8 fifo_count;
-+	struct fsi_i2c_master *i2c = port->master;
-+	u32 dummy = 0;
-+
-+	if (status & I2C_STAT_ERR) {
-+		rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_ERR, &dummy);
-+		if (rc)
-+			return rc;
-+
-+		if (status & I2C_STAT_NACK)
-+			return -EFAULT;
-+
-+		return -EIO;
-+	}
-+
-+	if (status & I2C_STAT_DAT_REQ) {
-+		fifo_count = GETFIELD(I2C_STAT_FIFO_COUNT, status);
-+
-+		if (msg->flags & I2C_M_RD)
-+			rc = fsi_i2c_read_fifo(port, msg, fifo_count);
-+		else
-+			rc = fsi_i2c_write_fifo(port, msg, fifo_count);
-+
-+		return rc;
-+	}
-+
-+	if (status & I2C_STAT_CMD_COMP) {
-+		if (port->xfrd < msg->len)
-+			rc = -ENODATA;
-+		else
-+			rc = msg->len;
-+	}
-+
-+	return rc;
-+}
-+
-+static int fsi_i2c_wait(struct fsi_i2c_port *port, struct i2c_msg *msg,
-+			unsigned long timeout)
-+{
-+	const unsigned long local_timeout = 2; /* jiffies */
-+	u32 status = 0;
-+	int rc;
-+
-+	do {
-+		rc = fsi_i2c_read_reg(port->master->fsi, I2C_FSI_STAT,
-+				      &status);
-+		if (rc)
-+			return rc;
-+
-+		if (status & I2C_STAT_ANY_RESP) {
-+			rc = fsi_i2c_handle_status(port, msg, status);
-+			if (rc < 0)
-+				return rc;
-+
-+			/* cmd complete and all data xfrd */
-+			if (rc == msg->len)
-+				return 0;
-+
-+			/* need to xfr more data, but maybe don't need wait */
-+			continue;
-+		}
-+
-+		set_current_state(TASK_UNINTERRUPTIBLE);
-+		schedule_timeout(local_timeout);
-+		timeout = (timeout < local_timeout) ? 0 :
-+			timeout - local_timeout;
-+	} while (timeout);
-+
-+	return -ETIME;
-+}
-+
- static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- 			int num)
- {
--	int rc;
-+	int i, rc;
-+	unsigned long start_time;
- 	struct fsi_i2c_port *port = adap->algo_data;
-+	struct i2c_msg *msg;
- 
- 	rc = fsi_i2c_set_port(port);
- 	if (rc)
- 		return rc;
- 
--	return -ENOSYS;
-+	for (i = 0; i < num; ++i) {
-+		msg = msgs + i;
-+		start_time = jiffies;
-+
-+		rc = fsi_i2c_start(port, msg, i == num - 1);
-+		if (rc)
-+			return rc;
-+
-+		rc = fsi_i2c_wait(port, msg,
-+				  adap->timeout - (jiffies - start_time));
-+		if (rc)
-+			return rc;
-+	}
-+
-+	return 0;
- }
- 
- static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-4-6-drivers-i2c-Add-I2C-master-locking-to-FSI-algorithm.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-4-6-drivers-i2c-Add-I2C-master-locking-to-FSI-algorithm.patch
deleted file mode 100644
index e649d62..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-4-6-drivers-i2c-Add-I2C-master-locking-to-FSI-algorithm.patch
+++ /dev/null
@@ -1,112 +0,0 @@
-From patchwork Wed May 10 15:52:40 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux, dev-4.10, v2,
- 4/6] drivers: i2c: Add I2C master locking to FSI algorithm
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 760699
-Message-Id: <1494431562-25101-5-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, cbostic@linux.vnet.ibm.com
-Date: Wed, 10 May 2017 10:52:40 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-Since there are many ports per master, each with it's own adapter and
-chardev, we need some locking to prevent xfers from changing the master
-state while other xfers are in progress.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/i2c/busses/i2c-fsi.c | 41 +++++++++++++++++++++++++++++++++++++----
- 1 file changed, 37 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
-index f690b16..d757aee 100644
---- a/drivers/i2c/busses/i2c-fsi.c
-+++ b/drivers/i2c/busses/i2c-fsi.c
-@@ -136,6 +136,8 @@ struct fsi_i2c_master {
- 	u8			fifo_size;
- 	struct list_head	ports;
- 	struct ida		ida;
-+	wait_queue_head_t	wait;
-+	struct semaphore	lock;
- };
- 
- struct fsi_i2c_port {
-@@ -171,6 +173,29 @@ static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg,
- 	return fsi_device_write(fsi, reg, &raw_data, sizeof(raw_data));
- }
- 
-+static int fsi_i2c_lock_master(struct fsi_i2c_master *i2c, int timeout)
-+{
-+	int rc;
-+
-+	rc = down_trylock(&i2c->lock);
-+	if (!rc)
-+		return 0;
-+
-+	rc = wait_event_interruptible_timeout(i2c->wait,
-+					      !down_trylock(&i2c->lock),
-+					      timeout);
-+	if (rc > 0)
-+		return 0;
-+
-+	return -EBUSY;
-+}
-+
-+static void fsi_i2c_unlock_master(struct fsi_i2c_master *i2c)
-+{
-+	up(&i2c->lock);
-+	wake_up(&i2c->wait);
-+}
-+
- static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c)
- {
- 	int rc;
-@@ -410,25 +435,31 @@ static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- 	struct fsi_i2c_port *port = adap->algo_data;
- 	struct i2c_msg *msg;
- 
--	rc = fsi_i2c_set_port(port);
-+	rc = fsi_i2c_lock_master(port->master, adap->timeout);
- 	if (rc)
- 		return rc;
- 
-+	rc = fsi_i2c_set_port(port);
-+	if (rc)
-+		goto unlock;
-+
- 	for (i = 0; i < num; ++i) {
- 		msg = msgs + i;
- 		start_time = jiffies;
- 
- 		rc = fsi_i2c_start(port, msg, i == num - 1);
- 		if (rc)
--			return rc;
-+			goto unlock;
- 
- 		rc = fsi_i2c_wait(port, msg,
- 				  adap->timeout - (jiffies - start_time));
- 		if (rc)
--			return rc;
-+			goto unlock;
- 	}
- 
--	return 0;
-+unlock:
-+	fsi_i2c_unlock_master(port->master);
-+	return rc;
- }
- 
- static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
-@@ -453,6 +484,8 @@ static int fsi_i2c_probe(struct device *dev)
- 	if (!i2c)
- 		return -ENOMEM;
- 
-+	init_waitqueue_head(&i2c->wait);
-+	sema_init(&i2c->lock, 1);
- 	i2c->fsi = to_fsi_dev(dev);
- 	i2c->idx = ida_simple_get(&fsi_i2c_ida, 1, INT_MAX, GFP_KERNEL);
- 	ida_init(&i2c->ida);
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-5-6-drivers-i2c-Add-bus-recovery-for-FSI-algorithm.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-5-6-drivers-i2c-Add-bus-recovery-for-FSI-algorithm.patch
deleted file mode 100644
index f9fc75d..0000000
--- a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-5-6-drivers-i2c-Add-bus-recovery-for-FSI-algorithm.patch
+++ /dev/null
@@ -1,117 +0,0 @@
-From patchwork Wed May 10 15:52:41 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [linux, dev-4.10, v2,
- 5/6] drivers: i2c: Add bus recovery for FSI algorithm
-From: eajames@linux.vnet.ibm.com
-X-Patchwork-Id: 760701
-Message-Id: <1494431562-25101-6-git-send-email-eajames@linux.vnet.ibm.com>
-To: openbmc@lists.ozlabs.org
-Cc: "Edward A. James" <eajames@us.ibm.com>, cbostic@linux.vnet.ibm.com
-Date: Wed, 10 May 2017 10:52:41 -0500
-
-From: "Edward A. James" <eajames@us.ibm.com>
-
-Bus recovery should reset the engine and force block the bus 9 times
-to recover most situations.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- drivers/i2c/busses/i2c-fsi.c | 76 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 76 insertions(+)
-
-diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
-index d757aee..4689479 100644
---- a/drivers/i2c/busses/i2c-fsi.c
-+++ b/drivers/i2c/busses/i2c-fsi.c
-@@ -467,6 +467,80 @@ static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
- 	return I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_10BIT_ADDR;
- }
- 
-+static int fsi_i2c_low_level_recover_bus(struct fsi_i2c_master *i2c)
-+{
-+	int i, rc;
-+	u32 mode, dummy = 0;
-+
-+	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode);
-+	if (rc)
-+		return rc;
-+
-+	mode |= I2C_MODE_DIAG;
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
-+	if (rc)
-+		return rc;
-+
-+	for (i = 0; i < 9; ++i) {
-+		rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SCL, &dummy);
-+		if (rc)
-+			return rc;
-+
-+		rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SCL, &dummy);
-+		if (rc)
-+			return rc;
-+	}
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SCL, &dummy);
-+	if (rc)
-+		return rc;
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SDA, &dummy);
-+	if (rc)
-+		return rc;
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SCL, &dummy);
-+	if (rc)
-+		return rc;
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SDA, &dummy);
-+	if (rc)
-+		return rc;
-+
-+	mode &= ~I2C_MODE_DIAG;
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
-+
-+	return rc;
-+}
-+
-+static int fsi_i2c_recover_bus(struct i2c_adapter *adap)
-+{
-+	int rc;
-+	u32 dummy = 0;
-+	struct fsi_i2c_port *port = adap->algo_data;
-+	struct fsi_i2c_master *i2c = port->master;
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy);
-+	if (rc)
-+		return rc;
-+
-+	rc = fsi_i2c_dev_init(i2c);
-+	if (rc)
-+		return rc;
-+
-+	rc = fsi_i2c_low_level_recover_bus(i2c);
-+	if (rc)
-+		return rc;
-+
-+	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_ERR, &dummy);
-+
-+	return rc;
-+}
-+
-+static struct i2c_bus_recovery_info fsi_i2c_bus_recovery_info = {
-+	.recover_bus = fsi_i2c_recover_bus,
-+};
-+
- static const struct i2c_algorithm fsi_i2c_algorithm = {
- 	.master_xfer = fsi_i2c_xfer,
- 	.functionality = fsi_i2c_functionality,
-@@ -514,6 +588,8 @@ static int fsi_i2c_probe(struct device *dev)
- 			port->adapter.owner = THIS_MODULE;
- 			port->adapter.dev.parent = dev;
- 			port->adapter.algo = &fsi_i2c_algorithm;
-+			port->adapter.bus_recovery_info =
-+				&fsi_i2c_bus_recovery_info;
- 			port->adapter.algo_data = port;
- 			/* number ports uniquely */
- 			port->adapter.nr = (i2c->idx * I2C_MASTER_NR_OFFSET) +
diff --git a/common/recipes-kernel/linux/linux-obmc/v2-0001-arm-dts-aspeed-Add-missing-clock-sources-for-barr.patch b/common/recipes-kernel/linux/linux-obmc/v2-0001-arm-dts-aspeed-Add-missing-clock-sources-for-barr.patch
deleted file mode 100644
index 01644c5..0000000
--- a/common/recipes-kernel/linux/linux-obmc/v2-0001-arm-dts-aspeed-Add-missing-clock-sources-for-barr.patch
+++ /dev/null
@@ -1,196 +0,0 @@
-From af9bc81e2158c326552c013d6591f533b69286e3 Mon Sep 17 00:00:00 2001
-From: "Edward A. James" <eajames@us.ibm.com>
-Date: Thu, 25 May 2017 09:59:09 -0500
-Subject: [PATCH linux dev-4.10 v2] arm: dts: aspeed: Add missing clock sources
- for barreleye
-
-Reorganize flash controllers into the ast2400 config. Barreleye wasn't
-booting with the new aspeed-smc driver.
-
-Signed-off-by: Edward A. James <eajames@us.ibm.com>
----
- arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts | 44 ++++++++--------------
- arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts  | 52 ++++++++------------------
- arch/arm/boot/dts/aspeed-g4.dtsi               | 34 +++++++++++++++++
- 3 files changed, 66 insertions(+), 64 deletions(-)
-
-diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts b/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
-index be1f2d1..7a616bb 100644
---- a/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
-+++ b/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
-@@ -31,34 +31,6 @@
- 		};
- 	};
- 
--	ahb {
--		bmc_pnor: fmc@1e620000 {
--			reg = < 0x1e620000 0x94
--				0x20000000 0x02000000 >;
--			#address-cells = <1>;
--			#size-cells = <0>;
--			compatible = "aspeed,ast2400-fmc";
--			flash@0 {
--				reg = < 0 >;
--				compatible = "jedec,spi-nor" ;
--#include "aspeed-bmc-opp-flash-layout.dtsi"
--			};
--		};
--
--		host_pnor: spi@1e630000 {
--			reg = < 0x1e630000 0x18
--				0x30000000 0x02000000 >;
--			#address-cells = <1>;
--			#size-cells = <0>;
--			compatible = "aspeed,ast2400-spi";
--			flash@0 {
--				reg = < 0 >;
--				compatible = "jedec,spi-nor" ;
--				label = "pnor";
--			};
--		};
--	};
--
- 	leds {
- 		compatible = "gpio-leds";
- 
-@@ -76,6 +48,22 @@
- 	};
- };
- 
-+&bmc_pnor {
-+	status = "okay";
-+	flash@0 {
-+		status = "okay";
-+		m25p,fast-read;
-+#include "aspeed-bmc-opp-flash-layout.dtsi"
-+	};
-+};
-+
-+&host_pnor {
-+	flash@0 {
-+		status = "okay";
-+		m25p,fast-read;
-+	};
-+};
-+
- &pinctrl {
- 	pinctrl-names = "default";
- 	pinctrl-0 = <&pinctrl_flbusy_default &pinctrl_flwp_default
-diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
-index b4faa1d..e55abe6 100644
---- a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
-+++ b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
-@@ -47,42 +47,6 @@
-                 };
-         };
- 
--	ahb {
--		bmc_pnor: fmc@1e620000 {
--			reg = < 0x1e620000 0x94
--				0x20000000 0x02000000 >;
--			#address-cells = <1>;
--			#size-cells = <0>;
--			compatible = "aspeed,ast2400-fmc";
--			aspeed,fmc-has-dma;
--			interrupts = <19>;
--			clocks = <&clk_ahb>;
--			clock-names = "ahb";
--			flash@0 {
--				reg = < 0 >;
--				compatible = "jedec,spi-nor" ;
--				m25p,fast-read;
--#include "aspeed-bmc-opp-flash-layout.dtsi"
--			};
--		};
--
--		host_pnor: spi@1e630000 {
--			reg = < 0x1e630000 0x18
--				0x30000000 0x02000000 >;
--			#address-cells = <1>;
--			#size-cells = <0>;
--			compatible = "aspeed,ast2400-spi";
--			clocks = <&clk_ahb>;
--			clock-names = "ahb";
--			flash {
--				reg = < 0 >;
--				compatible = "jedec,spi-nor" ;
--				label = "pnor";
--				m25p,fast-read;
--			};
--		};
--	};
--
- 	gpio-fsi {
- 		compatible = "fsi-master-gpio", "fsi-master";
- 
-@@ -94,6 +58,22 @@
- 	};
- };
- 
-+&bmc_pnor {
-+	status = "okay";
-+	flash@0 {
-+		status = "okay";
-+		m25p,fast-read;
-+#include "aspeed-bmc-opp-flash-layout.dtsi"
-+	};
-+};
-+
-+&host_pnor {
-+	flash@0 {
-+		status = "okay";
-+		m25p,fast-read;
-+	};
-+};
-+
- &pinctrl {
- 	pinctrl-names = "default";
- 	pinctrl-0 = <&pinctrl_flbusy_default &pinctrl_flwp_default
-diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
-index d8827d5..9fb7889 100644
---- a/arch/arm/boot/dts/aspeed-g4.dtsi
-+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
-@@ -44,6 +44,40 @@
- 		#size-cells = <1>;
- 		ranges;
- 
-+		bmc_pnor: fmc@1e620000 {
-+			reg = < 0x1e620000 0x94
-+				0x20000000 0x02000000 >;
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			compatible = "aspeed,ast2400-fmc";
-+			status = "disabled";
-+			aspeed,fmc-has-dma;
-+			interrupts = <19>;
-+			clocks = <&clk_ahb>;
-+			clock-names = "ahb";
-+			flash@0 {
-+				reg = < 0 >;
-+				compatible = "jedec,spi-nor" ;
-+				status = "disabled";
-+			};
-+		};
-+
-+		host_pnor: spi@1e630000 {
-+			reg = < 0x1e630000 0x18
-+				0x30000000 0x02000000 >;
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			compatible = "aspeed,ast2400-spi";
-+			status = "disabled";
-+			clocks = <&clk_ahb>;
-+			clock-names = "ahb";
-+			flash@0 {
-+				reg = < 0 >;
-+				compatible = "jedec,spi-nor" ;
-+				status = "disabled";
-+			};
-+		};
-+
- 		vic: interrupt-controller@1e6c0080 {
- 			compatible = "aspeed,ast2400-vic";
- 			interrupt-controller;
--- 
-1.8.3.1
-
diff --git a/common/recipes-kernel/linux/linux-obmc_4.10.bb b/common/recipes-kernel/linux/linux-obmc_4.10.bb
index 3a0dd9a..5b2cabd 100644
--- a/common/recipes-kernel/linux/linux-obmc_4.10.bb
+++ b/common/recipes-kernel/linux/linux-obmc_4.10.bb
@@ -1,6 +1,6 @@
 KBRANCH ?= "dev-4.10"
-LINUX_VERSION ?= "4.10.5"
+LINUX_VERSION ?= "4.10.17"
 
-SRCREV="8736136e756ec127de0bbe2c7e2de683204d4512"
+SRCREV="c694e47cbc1efc2bc181b2ac7137dfda04f974c2"
 
 require linux-obmc.inc