浏览代码

numa für RT tests eingebaut

Reinhard Russinger 5 年之前
父节点
当前提交
e701977fcf
共有 55 个文件被更改,包括 1953 次插入3 次删除
  1. 90 0
      board/PSG/iot2000/linux-4.4-patches/0001-stmmac-pci-Make-stmmac_pci_info-structure-constant.patch
  2. 95 0
      board/PSG/iot2000/linux-4.4-patches/0002-stmmac-pci-Use-stmmac_pci_info-for-all-devices.patch
  3. 61 0
      board/PSG/iot2000/linux-4.4-patches/0003-stmmac-pci-Make-stmmac_pci_find_phy_addr-truly-gener.patch
  4. 165 0
      board/PSG/iot2000/linux-4.4-patches/0004-stmmac-pci-Select-quark_pci_dmi_data-from-quark_defa.patch
  5. 167 0
      board/PSG/iot2000/linux-4.4-patches/0005-stmmac-pci-Use-dmi_system_id-table-for-retrieving-PH.patch
  6. 47 0
      board/PSG/iot2000/linux-4.4-patches/0006-stmmac-pci-Adjust-IOT2000-matching.patch
  7. 44 0
      board/PSG/iot2000/linux-4.4-patches/0007-serial-8250_exar-Adjust-IOT2000-matching.patch
  8. 45 0
      board/PSG/iot2000/linux-4.4-patches/0008-mfd-intel_quark_i2c_gpio-Adjust-IOT2000-matching.patch
  9. 86 0
      board/PSG/iot2000/linux-4.4-patches/0009-gpio-sch-use-gpiochip-data-pointer.patch
  10. 46 0
      board/PSG/iot2000/linux-4.4-patches/0010-gpio-sch-Use-devm_gpiochip_add_data-for-gpio-registr.patch
  11. 114 0
      board/PSG/iot2000/linux-4.4-patches/0011-gpio-sch-Fix-Oops-on-module-load-on-Asus-Eee-PC-1201.patch
  12. 45 0
      board/PSG/iot2000/linux-4.4-patches/0012-gpio-sch-Implement-.get_direction.patch
  13. 230 0
      board/PSG/iot2000/linux-4.4-patches/0013-gpio-sch-Add-interrupt-support.patch
  14. 44 0
      board/PSG/iot2000/linux-4.4-patches/0014-iot2000-hack-Work-around-DSDT-mistake.patch
  15. 42 0
      board/PSG/iot2000/linux-4.4-patches/0015-iot2000-hack-Adjust-pca9685-gpio-base-for-legacy-com.patch
  16. 99 0
      board/PSG/iot2000/linux-4.4-patches/0016-iot2000-hack-gpio-pca953x-provide-GPIO-base-based-on.patch
  17. 334 0
      board/PSG/iot2000/linux-4.4-patches/0017-iot2000-hack-gpio-pca953x-add-drive-property.patch
  18. 105 0
      board/PSG/iot2000/linux-4.4-patches/0018-iot2000-hack-pwm-pca-9685-Provide-chip-level-pwm_per.patch
  19. 39 0
      board/PSG/iot2000/linux-4.4-patches/rt-0001-spi-pca2xx-pci-Allow-MSI.patch
  20. 52 0
      board/PSG/iot2000/linux-4.4-patches/rt-0002-gpio-dwapb-Work-around-RT-full-s-enforced-IRQ-thread.patch
  21. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0001-stmmac-Add-support-for-SIMATIC-IOT2000-platform.patch
  22. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0002-serial-uapi-Add-support-for-bus-termination.patch
  23. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0003-serial-8250_pci-Use-symbolic-constants-for-EXAR-s-MP.patch
  24. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0004-serial-8250_pci-Fix-EXAR-feature-control-register-co.patch
  25. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0005-serial-8250_pci-Add-support-for-IOT2000-platform.patch
  26. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0006-serial-8250_pci-Add-support-for-red-user-LED-on-IOT2.patch
  27. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0007-spi-pxa2xx-Factor-out-handle_bad_msg.patch
  28. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0008-spi-pxa2xx-Prepare-for-edge-triggered-interrupts.patch
  29. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0009-spi-pca2xx-pci-Allow-MSI.patch
  30. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0010-efi-Move-efi_status_to_err-to-drivers-firmware-efi.patch
  31. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0011-efi-Add-capsule-update-support.patch
  32. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0012-x86-efi-Force-EFI-reboot-to-process-pending-capsules.patch
  33. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0013-efi-Add-misc-char-driver-interface-to-update-EFI-fir.patch
  34. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0014-efi-capsule-Make-efi_capsule_pending-lockless.patch
  35. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0015-efi-capsule-Move-capsule-to-the-stack-in-efi_capsule.patch
  36. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0016-efi-capsule-Allocate-whole-capsule-into-virtual-memo.patch
  37. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0017-efi-capsule-Fix-return-code-on-failing-kmap-vmap.patch
  38. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0018-efi-capsule-Remove-pr_debug-on-ENOMEM-or-EFAULT.patch
  39. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0019-efi-capsule-Clean-up-pr_err-info-messages.patch
  40. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0020-efi-capsule-Adjust-return-type-of-efi_capsule_setup_.patch
  41. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0021-efi-capsule-loader-Use-a-cached-copy-of-the-capsule-.patch
  42. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0022-efi-capsule-loader-Redirect-calls-to-efi_capsule_set.patch
  43. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0023-efi-capsule-loader-Use-page-addresses-rather-than-st.patch
  44. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0024-efi-capsule-Add-support-for-Quark-security-header.patch
  45. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0025-mfd-intel_quark_i2c_gpio-Use-dmi_system_id-table-for.patch
  46. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0026-mfd-intel_quark_i2c_gpio-Add-support-for-SIMATIC-IOT.patch
  47. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0027-iot2000-hack-Work-around-DSDT-mistake.patch
  48. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0028-gpio-pca953x-provide-GPIO-base-based-on-_UID.patch
  49. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0029-staging-iio-add-support-for-ADC1x8s102.patch
  50. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0030-adc1x8s102-support-ACPI-based-enumeration.patch
  51. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0031-gpio-pca953x-add-drive-property.patch
  52. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0032-pca9685-PCA9685-PWM-and-GPIO-multi-function-device.patch
  53. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0033-spi-pxa2xx-fixed-ACPI-based-enumeration-of-SPI-devic.patch
  54. 0 0
      board/PSG/iot2000/linux-4.4-patches_orig/0034-acpi-added-a-custom-DSDT-file.patch
  55. 3 3
      configs/iot2000_defconfig

+ 90 - 0
board/PSG/iot2000/linux-4.4-patches/0001-stmmac-pci-Make-stmmac_pci_info-structure-constant.patch

@@ -0,0 +1,90 @@
+From 2ca48f47b659edbd5cf4c4e55c420ef40712ce9b Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:17:57 +0200
+Subject: [PATCH 01/18] stmmac: pci: Make stmmac_pci_info structure constant
+
+Commit c5d5287ef0f763e836bf94659b3a6080358373f1 upstream.
+
+By removing the PCI device reference from the structure and passing it
+as parameters to the interested functions, we can make quark_pci_info
+const.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 3491e98bffc5..828d276748e3 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -42,17 +42,17 @@ struct stmmac_pci_dmi_data {
+ };
+ 
+ struct stmmac_pci_info {
+-	struct pci_dev *pdev;
+-	int (*setup)(struct plat_stmmacenet_data *plat,
+-		     struct stmmac_pci_info *info);
++	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
++		     const struct stmmac_pci_info *info);
+ 	struct stmmac_pci_dmi_data *dmi;
+ };
+ 
+-static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info)
++static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
++				    const struct stmmac_pci_info *info)
+ {
+ 	const char *name = dmi_get_system_info(DMI_BOARD_NAME);
+ 	const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG);
+-	unsigned int func = PCI_FUNC(info->pdev->devfn);
++	unsigned int func = PCI_FUNC(pdev->devfn);
+ 	struct stmmac_pci_dmi_data *dmi;
+ 
+ 	/*
+@@ -96,17 +96,17 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
+ 	plat->unicast_filter_entries = 1;
+ }
+ 
+-static int quark_default_data(struct plat_stmmacenet_data *plat,
+-			      struct stmmac_pci_info *info)
++static int quark_default_data(struct pci_dev *pdev,
++			      struct plat_stmmacenet_data *plat,
++			      const struct stmmac_pci_info *info)
+ {
+-	struct pci_dev *pdev = info->pdev;
+ 	int ret;
+ 
+ 	/*
+ 	 * Refuse to load the driver and register net device if MAC controller
+ 	 * does not connect to any PHY interface.
+ 	 */
+-	ret = stmmac_pci_find_phy_addr(info);
++	ret = stmmac_pci_find_phy_addr(pdev, info);
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -165,7 +165,7 @@ static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
+ 	{}
+ };
+ 
+-static struct stmmac_pci_info quark_pci_info = {
++static const struct stmmac_pci_info quark_pci_info = {
+ 	.setup = quark_default_data,
+ 	.dmi = quark_pci_dmi_data,
+ };
+@@ -227,9 +227,8 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ 	pci_set_master(pdev);
+ 
+ 	if (info) {
+-		info->pdev = pdev;
+ 		if (info->setup) {
+-			ret = info->setup(plat, info);
++			ret = info->setup(pdev, plat, info);
+ 			if (ret)
+ 				return ret;
+ 		}
+-- 
+2.16.4
+

+ 95 - 0
board/PSG/iot2000/linux-4.4-patches/0002-stmmac-pci-Use-stmmac_pci_info-for-all-devices.patch

@@ -0,0 +1,95 @@
+From 5222a576c02eed33b0499a7e632a56680742a885 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:17:58 +0200
+Subject: [PATCH 02/18] stmmac: pci: Use stmmac_pci_info for all devices
+
+Commit b6a4c8f013ea2dd1ead7ee14b44712189a7bc6c6 upstream.
+
+Make stmmac_default_data compatible with stmmac_pci_info.setup and use
+an info structure for all devices. This allows to make the probing more
+regular.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 36 +++++++++++++++---------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 828d276748e3..a60059032dc6 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -74,7 +74,9 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ 	return -ENODEV;
+ }
+ 
+-static void stmmac_default_data(struct plat_stmmacenet_data *plat)
++static int stmmac_default_data(struct pci_dev *pdev,
++			       struct plat_stmmacenet_data *plat,
++			       const struct stmmac_pci_info *info)
+ {
+ 	plat->bus_id = 1;
+ 	plat->phy_addr = 0;
+@@ -94,8 +96,14 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
+ 
+ 	/* Set default value for unicast filter entries */
+ 	plat->unicast_filter_entries = 1;
++
++	return 0;
+ }
+ 
++static const struct stmmac_pci_info stmmac_pci_info = {
++	.setup = stmmac_default_data,
++};
++
+ static int quark_default_data(struct pci_dev *pdev,
+ 			      struct plat_stmmacenet_data *plat,
+ 			      const struct stmmac_pci_info *info)
+@@ -226,14 +234,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ 
+ 	pci_set_master(pdev);
+ 
+-	if (info) {
+-		if (info->setup) {
+-			ret = info->setup(pdev, plat, info);
+-			if (ret)
+-				return ret;
+-		}
+-	} else
+-		stmmac_default_data(plat);
++	ret = info->setup(pdev, plat, info);
++	if (ret)
++		return ret;
+ 
+ 	pci_enable_msi(pdev);
+ 
+@@ -279,14 +282,21 @@ static int stmmac_pci_resume(struct device *dev)
+ 
+ static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume);
+ 
+-#define STMMAC_VENDOR_ID 0x700
++/* synthetic ID, no official vendor */
++#define PCI_VENDOR_ID_STMMAC 0x700
++
+ #define STMMAC_QUARK_ID  0x0937
+ #define STMMAC_DEVICE_ID 0x1108
+ 
++#define STMMAC_DEVICE(vendor_id, dev_id, info)	{	\
++	PCI_VDEVICE(vendor_id, dev_id),			\
++	.driver_data = (kernel_ulong_t)&info		\
++	}
++
+ static const struct pci_device_id stmmac_id_table[] = {
+-	{PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
+-	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
+-	{PCI_VDEVICE(INTEL, STMMAC_QUARK_ID), (kernel_ulong_t)&quark_pci_info},
++	STMMAC_DEVICE(STMMAC, STMMAC_DEVICE_ID, stmmac_pci_info),
++	STMMAC_DEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC, stmmac_pci_info),
++	STMMAC_DEVICE(INTEL, STMMAC_QUARK_ID, quark_pci_info),
+ 	{}
+ };
+ 
+-- 
+2.16.4
+

+ 61 - 0
board/PSG/iot2000/linux-4.4-patches/0003-stmmac-pci-Make-stmmac_pci_find_phy_addr-truly-gener.patch

@@ -0,0 +1,61 @@
+From d9478f26f2c620cf284f5022d3d852c47227e8da Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:17:59 +0200
+Subject: [PATCH 03/18] stmmac: pci: Make stmmac_pci_find_phy_addr truly
+ generic
+
+Commit c5f657e49c878756f21349f9e4b0f1c9631d5352 upstream.
+
+Move the special case for the early Galileo firmware into
+quark_default_setup. This allows to use stmmac_pci_find_phy_addr for
+non-quark cases.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index a60059032dc6..19cf9607618a 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -55,12 +55,8 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ 	unsigned int func = PCI_FUNC(pdev->devfn);
+ 	struct stmmac_pci_dmi_data *dmi;
+ 
+-	/*
+-	 * Galileo boards with old firmware don't support DMI. We always return
+-	 * 1 here, so at least first found MAC controller would be probed.
+-	 */
+ 	if (!name)
+-		return 1;
++		return -ENODEV;
+ 
+ 	for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) {
+ 		if (!strcmp(dmi->name, name) && dmi->func == func) {
+@@ -115,8 +111,18 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	 * does not connect to any PHY interface.
+ 	 */
+ 	ret = stmmac_pci_find_phy_addr(pdev, info);
+-	if (ret < 0)
+-		return ret;
++	if (ret < 0) {
++		/* Return error to the caller on DMI enabled boards. */
++		if (dmi_get_system_info(DMI_BOARD_NAME))
++			return ret;
++
++		/*
++		 * Galileo boards with old firmware don't support DMI. We always
++		 * use 1 here as PHY address, so at least the first found MAC
++		 * controller would be probed.
++		 */
++		ret = 1;
++	}
+ 
+ 	plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
+ 	plat->phy_addr = ret;
+-- 
+2.16.4
+

+ 165 - 0
board/PSG/iot2000/linux-4.4-patches/0004-stmmac-pci-Select-quark_pci_dmi_data-from-quark_defa.patch

@@ -0,0 +1,165 @@
+From 0747f34d4be27952be866461c97d386c29000817 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:18:00 +0200
+Subject: [PATCH 04/18] stmmac: pci: Select quark_pci_dmi_data from
+ quark_default_data
+
+Commit 7bc519b3ea04026877242328d2fe73cc8e6102bd upsteam.
+
+No need to carry this reference in stmmac_pci_info - the Quark-specific
+setup handler knows that it needs to use the Quark-specific DMI table.
+This also allows to drop the stmmac_pci_info reference from the setup
+handler parameter list.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 83 +++++++++++-------------
+ 1 file changed, 39 insertions(+), 44 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 19cf9607618a..9fe6368738ec 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -42,13 +42,11 @@ struct stmmac_pci_dmi_data {
+ };
+ 
+ struct stmmac_pci_info {
+-	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
+-		     const struct stmmac_pci_info *info);
+-	struct stmmac_pci_dmi_data *dmi;
++	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
+ };
+ 
+ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+-				    const struct stmmac_pci_info *info)
++				    struct stmmac_pci_dmi_data *dmi_data)
+ {
+ 	const char *name = dmi_get_system_info(DMI_BOARD_NAME);
+ 	const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG);
+@@ -58,7 +56,7 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ 	if (!name)
+ 		return -ENODEV;
+ 
+-	for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) {
++	for (dmi = dmi_data; dmi->name && *dmi->name; dmi++) {
+ 		if (!strcmp(dmi->name, name) && dmi->func == func) {
+ 			/* If asset tag is provided, match on it as well. */
+ 			if (dmi->asset_tag && strcmp(dmi->asset_tag, asset_tag))
+@@ -71,8 +69,7 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ }
+ 
+ static int stmmac_default_data(struct pci_dev *pdev,
+-			       struct plat_stmmacenet_data *plat,
+-			       const struct stmmac_pci_info *info)
++			       struct plat_stmmacenet_data *plat)
+ {
+ 	plat->bus_id = 1;
+ 	plat->phy_addr = 0;
+@@ -100,9 +97,40 @@ static const struct stmmac_pci_info stmmac_pci_info = {
+ 	.setup = stmmac_default_data,
+ };
+ 
++static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
++	{
++		.name = "Galileo",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "GalileoGen2",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "SIMATIC IOT2000",
++		.asset_tag = "6ES7647-0AA00-0YA2",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "SIMATIC IOT2000",
++		.asset_tag = "6ES7647-0AA00-1YA2",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "SIMATIC IOT2000",
++		.asset_tag = "6ES7647-0AA00-1YA2",
++		.func = 7,
++		.phy_addr = 1,
++	},
++	{}
++};
++
+ static int quark_default_data(struct pci_dev *pdev,
+-			      struct plat_stmmacenet_data *plat,
+-			      const struct stmmac_pci_info *info)
++			      struct plat_stmmacenet_data *plat)
+ {
+ 	int ret;
+ 
+@@ -110,7 +138,7 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	 * Refuse to load the driver and register net device if MAC controller
+ 	 * does not connect to any PHY interface.
+ 	 */
+-	ret = stmmac_pci_find_phy_addr(pdev, info);
++	ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi_data);
+ 	if (ret < 0) {
+ 		/* Return error to the caller on DMI enabled boards. */
+ 		if (dmi_get_system_info(DMI_BOARD_NAME))
+@@ -147,41 +175,8 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	return 0;
+ }
+ 
+-static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
+-	{
+-		.name = "Galileo",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "GalileoGen2",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-0YA2",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 7,
+-		.phy_addr = 1,
+-	},
+-	{}
+-};
+-
+ static const struct stmmac_pci_info quark_pci_info = {
+ 	.setup = quark_default_data,
+-	.dmi = quark_pci_dmi_data,
+ };
+ 
+ /**
+@@ -240,7 +235,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ 
+ 	pci_set_master(pdev);
+ 
+-	ret = info->setup(pdev, plat, info);
++	ret = info->setup(pdev, plat);
+ 	if (ret)
+ 		return ret;
+ 
+-- 
+2.16.4
+

+ 167 - 0
board/PSG/iot2000/linux-4.4-patches/0005-stmmac-pci-Use-dmi_system_id-table-for-retrieving-PH.patch

@@ -0,0 +1,167 @@
+From 1b2894107ad2d9de45402ecc4ffe14f075a08bbc Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:18:01 +0200
+Subject: [PATCH 05/18] stmmac: pci: Use dmi_system_id table for retrieving PHY
+ addresses
+
+Commit 8d78b69091845386b6096f3adae98f28b9bf96ed upstream.
+
+Avoids reimplementation of DMI matching in stmmac_pci_find_phy_addr.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 97 ++++++++++++++++--------
+ 1 file changed, 64 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 9fe6368738ec..279a1355d75f 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -34,36 +34,39 @@
+  * negative value of the address means that MAC controller is not connected
+  * with PHY.
+  */
+-struct stmmac_pci_dmi_data {
+-	const char *name;
+-	const char *asset_tag;
++struct stmmac_pci_func_data {
+ 	unsigned int func;
+ 	int phy_addr;
+ };
+ 
++struct stmmac_pci_dmi_data {
++	const struct stmmac_pci_func_data *func;
++	size_t nfuncs;
++};
++
+ struct stmmac_pci_info {
+ 	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
+ };
+ 
+ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+-				    struct stmmac_pci_dmi_data *dmi_data)
++				    const struct dmi_system_id *dmi_list)
+ {
+-	const char *name = dmi_get_system_info(DMI_BOARD_NAME);
+-	const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG);
+-	unsigned int func = PCI_FUNC(pdev->devfn);
+-	struct stmmac_pci_dmi_data *dmi;
+-
+-	if (!name)
++	const struct stmmac_pci_func_data *func_data;
++	const struct stmmac_pci_dmi_data *dmi_data;
++	const struct dmi_system_id *dmi_id;
++	int func = PCI_FUNC(pdev->devfn);
++	size_t n;
++
++	dmi_id = dmi_first_match(dmi_list);
++	if (!dmi_id)
+ 		return -ENODEV;
+ 
+-	for (dmi = dmi_data; dmi->name && *dmi->name; dmi++) {
+-		if (!strcmp(dmi->name, name) && dmi->func == func) {
+-			/* If asset tag is provided, match on it as well. */
+-			if (dmi->asset_tag && strcmp(dmi->asset_tag, asset_tag))
+-				continue;
+-			return dmi->phy_addr;
+-		}
+-	}
++	dmi_data = dmi_id->driver_data;
++	func_data = dmi_data->func;
++
++	for (n = 0; n < dmi_data->nfuncs; n++, func_data++)
++		if (func_data->func == func)
++			return func_data->phy_addr;
+ 
+ 	return -ENODEV;
+ }
+@@ -97,34 +100,62 @@ static const struct stmmac_pci_info stmmac_pci_info = {
+ 	.setup = stmmac_default_data,
+ };
+ 
+-static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
++static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = {
+ 	{
+-		.name = "Galileo",
+ 		.func = 6,
+ 		.phy_addr = 1,
+ 	},
++};
++
++static const struct stmmac_pci_dmi_data galileo_stmmac_dmi_data = {
++	.func = galileo_stmmac_func_data,
++	.nfuncs = ARRAY_SIZE(galileo_stmmac_func_data),
++};
++
++static const struct stmmac_pci_func_data iot2040_stmmac_func_data[] = {
+ 	{
+-		.name = "GalileoGen2",
+ 		.func = 6,
+ 		.phy_addr = 1,
+ 	},
+ 	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-0YA2",
+-		.func = 6,
++		.func = 7,
+ 		.phy_addr = 1,
+ 	},
++};
++
++static const struct stmmac_pci_dmi_data iot2040_stmmac_dmi_data = {
++	.func = iot2040_stmmac_func_data,
++	.nfuncs = ARRAY_SIZE(iot2040_stmmac_func_data),
++};
++
++static const struct dmi_system_id quark_pci_dmi[] = {
+ 	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 6,
+-		.phy_addr = 1,
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"),
++		},
++		.driver_data = (void *)&galileo_stmmac_dmi_data,
+ 	},
+ 	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 7,
+-		.phy_addr = 1,
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
++		},
++		.driver_data = (void *)&galileo_stmmac_dmi_data,
++	},
++	{
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
++			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
++					"6ES7647-0AA00-0YA2"),
++		},
++		.driver_data = (void *)&galileo_stmmac_dmi_data,
++	},
++	{
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
++			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
++					"6ES7647-0AA00-1YA2"),
++		},
++		.driver_data = (void *)&iot2040_stmmac_dmi_data,
+ 	},
+ 	{}
+ };
+@@ -138,7 +169,7 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	 * Refuse to load the driver and register net device if MAC controller
+ 	 * does not connect to any PHY interface.
+ 	 */
+-	ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi_data);
++	ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi);
+ 	if (ret < 0) {
+ 		/* Return error to the caller on DMI enabled boards. */
+ 		if (dmi_get_system_info(DMI_BOARD_NAME))
+-- 
+2.16.4
+

+ 47 - 0
board/PSG/iot2000/linux-4.4-patches/0006-stmmac-pci-Adjust-IOT2000-matching.patch

@@ -0,0 +1,47 @@
+From e3ba8c4f83c6c206a20e4645a37612b1e10580c6 Mon Sep 17 00:00:00 2001
+From: Su Bao Cheng <baocheng.su@siemens.com>
+Date: Fri, 12 Oct 2018 15:08:11 +0200
+Subject: [PATCH 06/18] stmmac: pci: Adjust IOT2000 matching
+
+Since there are more IOT2040 variants with identical hardware but
+different asset tags, the asset tag matching should be adjusted to
+support them.
+
+For the board name "SIMATIC IOT2000", currently there are 2 types of
+hardware, IOT2020 and IOT2040. The IOT2020 is identified by its unique
+asset tag. Match on it first. If we then match on the board name only,
+we will catch all IOT2040 variants. In the future there will be no other
+devices with the "SIMATIC IOT2000" DMI board name but different
+hardware.
+
+Signed-off-by: Su Bao Cheng <baocheng.su@siemens.com>
+Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 279a1355d75f..ac733d4d3ed4 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -149,11 +149,15 @@ static const struct dmi_system_id quark_pci_dmi[] = {
+ 		},
+ 		.driver_data = (void *)&galileo_stmmac_dmi_data,
+ 	},
++	/*
++	 * There are 2 types of SIMATIC IOT2000: IOT2020 and IOT2040.
++	 * The asset tag "6ES7647-0AA00-0YA2" is only for IOT2020 which
++	 * has only one pci network device while other asset tags are
++	 * for IOT2040 which has two.
++	 */
+ 	{
+ 		.matches = {
+ 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-1YA2"),
+ 		},
+ 		.driver_data = (void *)&iot2040_stmmac_dmi_data,
+ 	},
+-- 
+2.16.4
+

+ 44 - 0
board/PSG/iot2000/linux-4.4-patches/0007-serial-8250_exar-Adjust-IOT2000-matching.patch

@@ -0,0 +1,44 @@
+From df74e188ffc38176d4caba969e104d2ab2e4e609 Mon Sep 17 00:00:00 2001
+From: Su Bao Cheng <baocheng.su@siemens.com>
+Date: Fri, 12 Oct 2018 15:12:37 +0200
+Subject: [PATCH 07/18] serial: 8250_exar: Adjust IOT2000 matching
+
+Since there are more IOT2040 variants with identical hardware but
+different asset tags, the asset tag matching should be adjusted to
+support them.
+
+As only the IOT2040 variants have the Exar chip on board, matching on
+their board name is enough. In the future there will be no other devices
+with the "SIMATIC IOT2000" DMI board name but different hardware.
+
+Signed-off-by: Su Bao Cheng <baocheng.su@siemens.com>
+Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/tty/serial/8250/8250_exar.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
+index be82707d6cb8..3eb3a7674a0f 100644
+--- a/drivers/tty/serial/8250/8250_exar.c
++++ b/drivers/tty/serial/8250/8250_exar.c
+@@ -338,12 +338,15 @@ static const struct exar8250_platform iot2040_platform = {
+ 	.register_gpio = iot2040_register_gpio,
+ };
+ 
++/*
++ * For SIMATIC IOT2000, only IOT2040 and its variants have the Exar device,
++ * IOT2020 doesn't have. Therefore it is sufficient to match on the common
++ * board name after the device was found.
++ */
+ static const struct dmi_system_id exar_platforms[] = {
+ 	{
+ 		.matches = {
+ 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-1YA2"),
+ 		},
+ 		.driver_data = (void *)&iot2040_platform,
+ 	},
+-- 
+2.16.4
+

+ 45 - 0
board/PSG/iot2000/linux-4.4-patches/0008-mfd-intel_quark_i2c_gpio-Adjust-IOT2000-matching.patch

@@ -0,0 +1,45 @@
+From 6e378b789ebcfcdc4ae957b25f1ac6eb2ef64edc Mon Sep 17 00:00:00 2001
+From: Su Bao Cheng <baocheng.su@siemens.com>
+Date: Fri, 12 Oct 2018 15:05:07 +0200
+Subject: [PATCH 08/18] mfd: intel_quark_i2c_gpio: Adjust IOT2000 matching
+
+Since there are more IOT2040 variants with identical hardware but
+different asset tags, the asset tag matching should be adjusted to
+support them.
+
+For the board name "SIMATIC IOT2000", currently there are 2 types of
+hardware, IOT2020 and IOT2040. Both are identical regarding the
+intel_quark_i2c_gpio. In the future there will be no other devices with
+the "SIMATIC IOT2000" DMI board name but different hardware. So remove
+the asset tag matching from this driver.
+
+Signed-off-by: Su Bao Cheng <baocheng.su@siemens.com>
+Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/mfd/intel_quark_i2c_gpio.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c
+index 1c09604978d3..ad70a058bea8 100644
+--- a/drivers/mfd/intel_quark_i2c_gpio.c
++++ b/drivers/mfd/intel_quark_i2c_gpio.c
+@@ -76,16 +76,6 @@ static const struct dmi_system_id dmi_platform_info[] = {
+ 	{
+ 		.matches = {
+ 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-0YA2"),
+-		},
+-		.driver_data = (void *)400000,
+-	},
+-	{
+-		.matches = {
+-			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-1YA2"),
+ 		},
+ 		.driver_data = (void *)400000,
+ 	},
+-- 
+2.16.4
+

+ 86 - 0
board/PSG/iot2000/linux-4.4-patches/0009-gpio-sch-use-gpiochip-data-pointer.patch

@@ -0,0 +1,86 @@
+From cf3d1330c71d47c4cdb9268f68d2ee5931890d93 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Mon, 7 Dec 2015 14:21:49 +0100
+Subject: [PATCH 09/18] gpio: sch: use gpiochip data pointer
+
+This makes the driver use the data pointer added to the gpio_chip
+to store a pointer to the state container instead of relying on
+container_of().
+
+Cc: Chang Rebecca Swee Fun <rebecca.swee.fun.chang@intel.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-sch.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index b72906f5b999..23907fc080a3 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -41,8 +41,6 @@ struct sch_gpio {
+ 	unsigned short resume_base;
+ };
+ 
+-#define to_sch_gpio(gc)	container_of(gc, struct sch_gpio, chip)
+-
+ static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+ 				unsigned reg)
+ {
+@@ -65,7 +63,7 @@ static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
+ 
+ static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -80,7 +78,7 @@ static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
+ static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
+ 			     int val)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -97,7 +95,7 @@ static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
+ 
+ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+ 	sch_gpio_reg_set(gc, gpio_num, GIO, 1);
+@@ -112,7 +110,7 @@ static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+ 
+ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+ 	sch_gpio_reg_set(gc, gpio_num, GLV, val);
+@@ -122,7 +120,7 @@ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 				  int val)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+ 	sch_gpio_reg_set(gc, gpio_num, GIO, 0);
+@@ -217,7 +215,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 
+ 	platform_set_drvdata(pdev, sch);
+ 
+-	return gpiochip_add(&sch->chip);
++	return gpiochip_add_data(&sch->chip, sch);
+ }
+ 
+ static int sch_gpio_remove(struct platform_device *pdev)
+-- 
+2.16.4
+

+ 46 - 0
board/PSG/iot2000/linux-4.4-patches/0010-gpio-sch-Use-devm_gpiochip_add_data-for-gpio-registr.patch

@@ -0,0 +1,46 @@
+From 6a930e4d040061edcaf0c3e3e43a10acdc20f09c Mon Sep 17 00:00:00 2001
+From: Laxman Dewangan <ldewangan@nvidia.com>
+Date: Mon, 22 Feb 2016 17:43:28 +0530
+Subject: [PATCH 10/18] gpio: sch: Use devm_gpiochip_add_data() for gpio
+ registration
+
+Use devm_gpiochip_add_data() for GPIO registration and remove the
+need of driver callback .remove.
+
+Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
+---
+ drivers/gpio/gpio-sch.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 23907fc080a3..bbf9b2a34da8 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -215,15 +215,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 
+ 	platform_set_drvdata(pdev, sch);
+ 
+-	return gpiochip_add_data(&sch->chip, sch);
+-}
+-
+-static int sch_gpio_remove(struct platform_device *pdev)
+-{
+-	struct sch_gpio *sch = platform_get_drvdata(pdev);
+-
+-	gpiochip_remove(&sch->chip);
+-	return 0;
++	return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
+ }
+ 
+ static struct platform_driver sch_gpio_driver = {
+@@ -231,7 +223,6 @@ static struct platform_driver sch_gpio_driver = {
+ 		.name = "sch_gpio",
+ 	},
+ 	.probe		= sch_gpio_probe,
+-	.remove		= sch_gpio_remove,
+ };
+ 
+ module_platform_driver(sch_gpio_driver);
+-- 
+2.16.4
+

+ 114 - 0
board/PSG/iot2000/linux-4.4-patches/0011-gpio-sch-Fix-Oops-on-module-load-on-Asus-Eee-PC-1201.patch

@@ -0,0 +1,114 @@
+From 9fd1991d762b6092f462f3cc551b2d7df3009b52 Mon Sep 17 00:00:00 2001
+From: Colin Pitrat <colin.pitrat@gmail.com>
+Date: Sat, 18 Jun 2016 19:05:04 +0100
+Subject: [PATCH 11/18] gpio: sch: Fix Oops on module load on Asus Eee PC 1201
+
+This fixes the issue descirbe in bug 117531
+(https://bugzilla.kernel.org/show_bug.cgi?id=117531).
+It's a regression introduced in linux 4.5 that causes a Oops at load of
+gpio_sch and prevents powering off the computer.
+
+The issue is that sch_gpio_reg_set is called in sch_gpio_probe before
+gpio_chip data is initialized with the pointer to the sch_gpio struct. As
+sch_gpio_reg_set calls gpiochip_get_data, it returns NULL which causes
+the Oops.
+
+The patch follows Mika's advice (https://lkml.org/lkml/2016/5/9/61) and
+consists in modifying sch_gpio_reg_get and sch_gpio_reg_set to take a
+sch_gpio struct directly instead of a gpio_chip, which avoids the call to
+gpiochip_get_data.
+
+Thanks Mika for your patience with me :-)
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Colin Pitrat <colin.pitrat@gmail.com>
+Acked-by: Alexandre Courbot <acourbot@nvidia.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-sch.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index bbf9b2a34da8..5f72b177fc80 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -61,9 +61,8 @@ static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
+ 	return gpio % 8;
+ }
+ 
+-static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
++static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned gpio, unsigned reg)
+ {
+-	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -75,10 +74,9 @@ static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
+ 	return reg_val;
+ }
+ 
+-static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
++static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned gpio, unsigned reg,
+ 			     int val)
+ {
+-	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -98,14 +96,15 @@ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+-	sch_gpio_reg_set(gc, gpio_num, GIO, 1);
++	sch_gpio_reg_set(sch, gpio_num, GIO, 1);
+ 	spin_unlock(&sch->lock);
+ 	return 0;
+ }
+ 
+ static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+ {
+-	return sch_gpio_reg_get(gc, gpio_num, GLV);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
++	return sch_gpio_reg_get(sch, gpio_num, GLV);
+ }
+ 
+ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+@@ -113,7 +112,7 @@ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+-	sch_gpio_reg_set(gc, gpio_num, GLV, val);
++	sch_gpio_reg_set(sch, gpio_num, GLV, val);
+ 	spin_unlock(&sch->lock);
+ }
+ 
+@@ -123,7 +122,7 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+-	sch_gpio_reg_set(gc, gpio_num, GIO, 0);
++	sch_gpio_reg_set(sch, gpio_num, GIO, 0);
+ 	spin_unlock(&sch->lock);
+ 
+ 	/*
+@@ -182,13 +181,13 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 		 * GPIO7 is configured by the CMC as SLPIOVR
+ 		 * Enable GPIO[9:8] core powered gpios explicitly
+ 		 */
+-		sch_gpio_reg_set(&sch->chip, 8, GEN, 1);
+-		sch_gpio_reg_set(&sch->chip, 9, GEN, 1);
++		sch_gpio_reg_set(sch, 8, GEN, 1);
++		sch_gpio_reg_set(sch, 9, GEN, 1);
+ 		/*
+ 		 * SUS_GPIO[2:0] enabled by default
+ 		 * Enable SUS_GPIO3 resume powered gpio explicitly
+ 		 */
+-		sch_gpio_reg_set(&sch->chip, 13, GEN, 1);
++		sch_gpio_reg_set(sch, 13, GEN, 1);
+ 		break;
+ 
+ 	case PCI_DEVICE_ID_INTEL_ITC_LPC:
+-- 
+2.16.4
+

+ 45 - 0
board/PSG/iot2000/linux-4.4-patches/0012-gpio-sch-Implement-.get_direction.patch

@@ -0,0 +1,45 @@
+From 8fec046f568e2b946abd55a82d5417717a115b21 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Wed, 27 Jun 2018 10:39:31 +0200
+Subject: [PATCH 12/18] gpio: sch: Implement .get_direction()
+
+It's pretty simple to implement the .get_direction() for this
+chip, so let's just do it.
+
+Cc: Denis Turischev <denis.turischev@compulab.co.il>
+Cc: Daniel Krueger <daniel.krueger@systec-electronic.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-sch.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 5f72b177fc80..6715828c3940 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -138,6 +138,13 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 	return 0;
+ }
+ 
++static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num)
++{
++	struct sch_gpio *sch = gpiochip_get_data(gc);
++
++	return sch_gpio_reg_get(sch, gpio_num, GIO);
++}
++
+ static struct gpio_chip sch_gpio_chip = {
+ 	.label			= "sch_gpio",
+ 	.owner			= THIS_MODULE,
+@@ -145,6 +152,7 @@ static struct gpio_chip sch_gpio_chip = {
+ 	.get			= sch_gpio_get,
+ 	.direction_output	= sch_gpio_direction_out,
+ 	.set			= sch_gpio_set,
++	.get_direction		= sch_gpio_get_direction,
+ };
+ 
+ static int sch_gpio_probe(struct platform_device *pdev)
+-- 
+2.16.4
+

+ 230 - 0
board/PSG/iot2000/linux-4.4-patches/0013-gpio-sch-Add-interrupt-support.patch

@@ -0,0 +1,230 @@
+From 53c90b014f54743b5a2180f90b90b1f198535583 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Wed, 17 Apr 2019 22:26:22 +0200
+Subject: [PATCH 13/18] gpio: sch: Add interrupt support
+
+Validated on the Quark platform, this adds interrupt support on rising
+and/or falling edges.
+
+Backported from upstream, skipping clean roll-back or errors due to some
+missing devm_* services.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpio-sch.c | 140 +++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 133 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 6715828c3940..1d1dadebc8c1 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -32,6 +32,10 @@
+ #define GEN	0x00
+ #define GIO	0x04
+ #define GLV	0x08
++#define GTPE	0x0c
++#define GTNE	0x10
++#define GGPE	0x14
++#define GTS	0x1c
+ 
+ struct sch_gpio {
+ 	struct gpio_chip chip;
+@@ -39,6 +43,7 @@ struct sch_gpio {
+ 	unsigned short iobase;
+ 	unsigned short core_base;
+ 	unsigned short resume_base;
++	int irq_base;
+ };
+ 
+ static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+@@ -94,10 +99,11 @@ static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned gpio, unsigned reg,
+ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+ {
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
++	unsigned long flags;
+ 
+-	spin_lock(&sch->lock);
++	spin_lock_irqsave(&sch->lock, flags);
+ 	sch_gpio_reg_set(sch, gpio_num, GIO, 1);
+-	spin_unlock(&sch->lock);
++	spin_unlock_irqrestore(&sch->lock, flags);
+ 	return 0;
+ }
+ 
+@@ -110,20 +116,22 @@ static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ {
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
++	unsigned long flags;
+ 
+-	spin_lock(&sch->lock);
++	spin_lock_irqsave(&sch->lock, flags);
+ 	sch_gpio_reg_set(sch, gpio_num, GLV, val);
+-	spin_unlock(&sch->lock);
++	spin_unlock_irqrestore(&sch->lock, flags);
+ }
+ 
+ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 				  int val)
+ {
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
++	unsigned long flags;
+ 
+-	spin_lock(&sch->lock);
++	spin_lock_irqsave(&sch->lock, flags);
+ 	sch_gpio_reg_set(sch, gpio_num, GIO, 0);
+-	spin_unlock(&sch->lock);
++	spin_unlock_irqrestore(&sch->lock, flags);
+ 
+ 	/*
+ 	 * according to the datasheet, writing to the level register has no
+@@ -145,6 +153,12 @@ static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num)
+ 	return sch_gpio_reg_get(sch, gpio_num, GIO);
+ }
+ 
++static int sch_gpio_to_irq(struct gpio_chip *gpio, unsigned int offset)
++{
++	struct sch_gpio *sch = gpiochip_get_data(gpio);
++	return sch->irq_base + offset;
++}
++
+ static struct gpio_chip sch_gpio_chip = {
+ 	.label			= "sch_gpio",
+ 	.owner			= THIS_MODULE,
+@@ -153,12 +167,96 @@ static struct gpio_chip sch_gpio_chip = {
+ 	.direction_output	= sch_gpio_direction_out,
+ 	.set			= sch_gpio_set,
+ 	.get_direction		= sch_gpio_get_direction,
++	.to_irq			= sch_gpio_to_irq,
+ };
+ 
++static u32 sch_sci_handler(void *context)
++{
++	struct sch_gpio *sch = context;
++	unsigned long core_status, resume_status;
++	unsigned int resume_gpios, offset;
++
++	core_status = inl(sch->iobase + GTS);
++	resume_status = inl(sch->iobase + GTS + 0x20);
++
++	if (core_status == 0 && resume_status == 0)
++		return ACPI_INTERRUPT_NOT_HANDLED;
++
++	for_each_set_bit(offset, &core_status, sch->resume_base)
++		generic_handle_irq(sch->irq_base + offset);
++
++	resume_gpios = sch->chip.ngpio - sch->resume_base;
++	for_each_set_bit(offset, &resume_status, resume_gpios)
++		generic_handle_irq(sch->irq_base + sch->resume_base + offset);
++
++	outl(core_status, sch->iobase + GTS);
++	outl(resume_status, sch->iobase + GTS + 0x20);
++
++	return ACPI_INTERRUPT_HANDLED;
++}
++
++static int sch_irq_type(struct irq_data *d, unsigned int type)
++{
++	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
++	struct sch_gpio *sch = gc->private;
++	unsigned int gpio_num = d->irq - sch->irq_base;
++	unsigned long flags;
++	int rising = 0;
++	int falling = 0;
++
++	switch (type & IRQ_TYPE_SENSE_MASK) {
++	case IRQ_TYPE_EDGE_RISING:
++		rising = 1;
++		break;
++	case IRQ_TYPE_EDGE_FALLING:
++		falling = 1;
++		break;
++	case IRQ_TYPE_EDGE_BOTH:
++		rising = 1;
++		falling = 1;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	spin_lock_irqsave(&sch->lock, flags);
++	sch_gpio_reg_set(sch, gpio_num, GTPE, rising);
++	sch_gpio_reg_set(sch, gpio_num, GTNE, falling);
++	spin_unlock_irqrestore(&sch->lock, flags);
++
++	return 0;
++}
++
++static void sch_irq_set_enable(struct irq_data *d, int val)
++{
++	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
++	struct sch_gpio *sch = gc->private;
++	unsigned int gpio_num = d->irq - sch->irq_base;
++	unsigned long flags;
++
++	spin_lock_irqsave(&sch->lock, flags);
++	sch_gpio_reg_set(sch, gpio_num, GGPE, val);
++	spin_unlock_irqrestore(&sch->lock, flags);
++}
++
++static void sch_irq_mask(struct irq_data *d)
++{
++	sch_irq_set_enable(d, 0);
++}
++
++static void sch_irq_unmask(struct irq_data *d)
++{
++	sch_irq_set_enable(d, 1);
++}
++
+ static int sch_gpio_probe(struct platform_device *pdev)
+ {
++	struct irq_chip_generic *gc;
++	struct irq_chip_type *ct;
+ 	struct sch_gpio *sch;
+ 	struct resource *res;
++	acpi_status status;
++	int irq_base, ret;
+ 
+ 	sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
+ 	if (!sch)
+@@ -222,7 +320,35 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 
+ 	platform_set_drvdata(pdev, sch);
+ 
+-	return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
++	ret = devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
++	if (ret)
++		return ret;
++
++	irq_base = irq_alloc_descs(-1, 0, sch->chip.ngpio, NUMA_NO_NODE);
++	if (irq_base < 0)
++		return irq_base;
++	sch->irq_base = irq_base;
++
++	gc = irq_alloc_generic_chip("sch_gpio", 1, irq_base,
++				    NULL, handle_simple_irq);
++	if (!gc)
++		return -ENOMEM;
++
++	gc->private = sch;
++	ct = gc->chip_types;
++
++	ct->chip.irq_mask = sch_irq_mask;
++	ct->chip.irq_unmask = sch_irq_unmask;
++	ct->chip.irq_set_type = sch_irq_type;
++
++	irq_setup_generic_chip(gc, IRQ_MSK(sch->chip.ngpio),
++			       0, IRQ_NOREQUEST | IRQ_NOPROBE, 0);
++
++	status = acpi_install_sci_handler(sch_sci_handler, sch);
++	if (ACPI_FAILURE(status))
++		return -EINVAL;
++
++	return 0;
+ }
+ 
+ static struct platform_driver sch_gpio_driver = {
+-- 
+2.16.4
+

+ 44 - 0
board/PSG/iot2000/linux-4.4-patches/0014-iot2000-hack-Work-around-DSDT-mistake.patch

@@ -0,0 +1,44 @@
+From f43a54ec8a8b5f070d4b1b59f3d47dc03f74ad32 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 25 May 2017 11:09:42 +0200
+Subject: [PATCH 14/18] iot2000-hack: Work around DSDT mistake
+
+Until we have a new firmware revision, fix up the incorrect GPIO
+interrupt pin in software.
+
+Nothing for upstream.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpiolib-acpi.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
+index 16a7b6816744..304855b3ecb8 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -10,6 +10,7 @@
+  * published by the Free Software Foundation.
+  */
+ 
++#include <linux/dmi.h>
+ #include <linux/errno.h>
+ #include <linux/gpio.h>
+ #include <linux/gpio/consumer.h>
+@@ -408,6 +409,13 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
+ 		if (pin_index >= agpio->pin_table_length)
+ 			return 1;
+ 
++		if (!strcmp(dmi_get_system_info(DMI_BOARD_NAME),
++			    "SIMATIC IOT2000") &&
++		    !strcmp(agpio->resource_source.string_ptr,
++			    "\\_SB.PCI0.GIP0.GPO") &&
++		    agpio->pin_table[pin_index] == 9)
++			agpio->pin_table[pin_index] = 1;
++
+ 		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
+ 					      agpio->pin_table[pin_index]);
+ 		lookup->info.gpioint =
+-- 
+2.16.4
+

+ 42 - 0
board/PSG/iot2000/linux-4.4-patches/0015-iot2000-hack-Adjust-pca9685-gpio-base-for-legacy-com.patch

@@ -0,0 +1,42 @@
+From 88f2d0ccdee1f1890af0d049c60fe24f6c6eb048 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 25 May 2017 13:05:12 +0200
+Subject: [PATCH 15/18] iot2000-hack: Adjust pca9685-gpio base for legacy
+ compatibility
+
+mraa and the Arduino runtime expect this.
+
+Not for upstream.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/pwm/pwm-pca9685.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
+index d2b92e940e38..611b9263a896 100644
+--- a/drivers/pwm/pwm-pca9685.c
++++ b/drivers/pwm/pwm-pca9685.c
+@@ -19,6 +19,7 @@
+  * this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+ 
++#include <linux/dmi.h>
+ #include <linux/acpi.h>
+ #include <linux/gpio/driver.h>
+ #include <linux/i2c.h>
+@@ -222,7 +223,10 @@ static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
+ 	pca->gpio.direction_output = pca9685_pwm_gpio_direction_output;
+ 	pca->gpio.get = pca9685_pwm_gpio_get;
+ 	pca->gpio.set = pca9685_pwm_gpio_set;
+-	pca->gpio.base = -1;
++	if (!strcmp(dmi_get_system_info(DMI_BOARD_NAME), "SIMATIC IOT2000"))
++		pca->gpio.base = 64;
++	else
++		pca->gpio.base = -1;
+ 	pca->gpio.ngpio = PCA9685_MAXCHAN;
+ 	pca->gpio.can_sleep = true;
+ 
+-- 
+2.16.4
+

+ 99 - 0
board/PSG/iot2000/linux-4.4-patches/0016-iot2000-hack-gpio-pca953x-provide-GPIO-base-based-on.patch

@@ -0,0 +1,99 @@
+From 5c102aea3f4ffea811eec719edd638fc7888e9c3 Mon Sep 17 00:00:00 2001
+From: Yong Li <sdliyong@gmail.com>
+Date: Thu, 31 Mar 2016 15:33:08 +0800
+Subject: [PATCH 16/18] iot2000-hack: gpio: pca953x: provide GPIO base based on
+ _UID
+
+Custom kernel for Intel Galileo Gen2 provides and moreover libmraa relies on
+the continuous GPIO space. To do such we have to configure GPIO base per each
+GPIO expander. The only value we can use is the ACPI _UID.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+Upstream-status: Inappropriate, custom code for legacy userspace
+Signed-off-by: Saul Wold <sgw@linux.intel.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Yong Li <sdliyong@gmail.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpio-pca953x.c | 44 +++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 37 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index b45ba6be69ef..8b467c0db1cb 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -82,12 +82,6 @@ static const struct i2c_device_id pca953x_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, pca953x_id);
+ 
+-static const struct acpi_device_id pca953x_acpi_ids[] = {
+-	{ "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, },
+-	{ }
+-};
+-MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
+-
+ #define MAX_BANK 5
+ #define BANK_SZ 8
+ 
+@@ -119,6 +113,35 @@ static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
+ 	return container_of(gc, struct pca953x_chip, gpio_chip);
+ }
+ 
++struct pca953x_info {
++	kernel_ulong_t driver_data;
++	void (*setup)(struct pca953x_chip *chip);
++};
++
++static void pca953x_setup_int3491(struct pca953x_chip *chip)
++{
++	struct acpi_device *adev = ACPI_COMPANION(&chip->client->dev);
++	unsigned int uid;
++
++	if (kstrtouint(acpi_device_uid(adev), 0, &uid) || !uid--)
++		return;
++
++	chip->gpio_start = 8 /* sch_gpio */ +
++			   8 /* gpio-dwapb */ +
++			  16 /* pca9535 */ * uid;
++}
++
++static const struct pca953x_info pca953x_info_int3491 = {
++	.driver_data = 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL,
++	.setup = pca953x_setup_int3491,
++};
++
++static const struct acpi_device_id pca953x_acpi_ids[] = {
++	{ "INT3491",  (kernel_ulong_t)&pca953x_info_int3491 },
++	{ }
++};
++MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
++
+ static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
+ 				int off)
+ {
+@@ -731,12 +754,19 @@ static int pca953x_probe(struct i2c_client *client,
+ 		chip->driver_data = id->driver_data;
+ 	} else {
+ 		const struct acpi_device_id *id;
++		const struct pca953x_info *info;
+ 
+ 		id = acpi_match_device(pca953x_acpi_ids, &client->dev);
+ 		if (!id)
+ 			return -ENODEV;
+ 
+-		chip->driver_data = id->driver_data;
++		info = (struct pca953x_info *)id->driver_data;
++		if (!info)
++			return -ENODEV;
++
++		chip->driver_data = info->driver_data;
++		if (info->setup)
++			info->setup(chip);
+ 	}
+ 
+ 	chip->chip_type = PCA_CHIP_TYPE(chip->driver_data);
+-- 
+2.16.4
+

+ 334 - 0
board/PSG/iot2000/linux-4.4-patches/0017-iot2000-hack-gpio-pca953x-add-drive-property.patch

@@ -0,0 +1,334 @@
+From a66a980a3520859c1a01fc65f76c4f2abd2a2eed Mon Sep 17 00:00:00 2001
+From: Yong Li <sdliyong@gmail.com>
+Date: Thu, 31 Mar 2016 15:33:09 +0800
+Subject: [PATCH 17/18] iot2000-hack: gpio-pca953x: add "drive" property
+
+Galileo gen 2 has support for setting GPIO modes. Expose these
+properties through the GPIO sysfs interface. This approach is bit hacky,
+since it changes the interface semantics.
+
+The original patch was by Josef Ahmad <josef.ahmad@linux.intel.com> and
+made on top of kernel 3.8.
+
+Not for upstream.
+
+Signed-off-by: Ismo Puustinen <ismo.puustinen@intel.com>
+Signed-off-by: Jussi Laako <jussi.laako@linux.intel.com>
+Signed-off-by: Saul Wold <sgw@linux.intel.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Yong Li <sdliyong@gmail.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpio-pca953x.c   | 42 +++++++++++++++++++++++
+ drivers/gpio/gpiolib-sysfs.c  | 78 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/gpio/gpiolib.c        | 17 ++++++++++
+ drivers/gpio/gpiolib.h        |  4 +++
+ include/asm-generic/gpio.h    |  5 +++
+ include/linux/gpio.h          | 10 ++++++
+ include/linux/gpio/consumer.h | 11 ++++++
+ include/linux/gpio/driver.h   |  2 ++
+ 8 files changed, 169 insertions(+)
+
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index 8b467c0db1cb..ca1f6f4d6f59 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -40,6 +40,8 @@
+ #define PCA957X_INTS		7
+ 
+ #define PCAL953X_IN_LATCH	34
++#define PCAL953X_PUPD_EN	35
++#define PCAL953X_PUPD_SEL	36
+ #define PCAL953X_INT_MASK	37
+ #define PCAL953X_INT_STAT	38
+ 
+@@ -380,6 +382,43 @@ exit:
+ 	mutex_unlock(&chip->i2c_lock);
+ }
+ 
++static int pca953x_gpio_set_drive(struct gpio_chip *gc,
++				 unsigned off, unsigned mode)
++{
++	struct pca953x_chip *chip;
++	int ret = 0;
++	int val;
++
++	chip = container_of(gc, struct pca953x_chip, gpio_chip);
++
++	if (!(chip->driver_data & PCA_PCAL))
++		return -EINVAL;
++
++	mutex_lock(&chip->i2c_lock);
++
++	switch (mode) {
++	case GPIOF_DRIVE_PULLUP:
++		ret = pca953x_write_single(chip, PCAL953X_PUPD_EN, 1, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_SEL, 1, off);
++		break;
++	case GPIOF_DRIVE_PULLDOWN:
++		ret = pca953x_write_single(chip, PCAL953X_PUPD_EN, 1, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_SEL, 0, off);
++		break;
++	case GPIOF_DRIVE_STRONG:
++	case GPIOF_DRIVE_HIZ:
++		ret = pca953x_read_single(chip, PCAL953X_PUPD_EN, &val, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_EN, 0, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_SEL, val, off);
++		break;
++	default:
++		ret = -EINVAL;
++	}
++
++	mutex_unlock(&chip->i2c_lock);
++	return ret;
++}
++
+ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+ {
+ 	struct gpio_chip *gc;
+@@ -398,6 +437,9 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+ 	gc->dev = &chip->client->dev;
+ 	gc->owner = THIS_MODULE;
+ 	gc->names = chip->names;
++
++	if (chip->driver_data & PCA_PCAL)
++		gc->set_drive = pca953x_gpio_set_drive;
+ }
+ 
+ #ifdef CONFIG_GPIO_PCA953X_IRQ
+diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
+index b57ed8e55ab5..72a8647146fa 100644
+--- a/drivers/gpio/gpiolib-sysfs.c
++++ b/drivers/gpio/gpiolib-sysfs.c
+@@ -7,6 +7,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/kdev_t.h>
+ #include <linux/slab.h>
++#include <linux/gpio.h>
+ 
+ #include "gpiolib.h"
+ 
+@@ -350,6 +351,82 @@ static ssize_t active_low_store(struct device *dev,
+ }
+ static DEVICE_ATTR_RW(active_low);
+ 
++
++static ssize_t gpio_drive_show(struct device *dev,
++		struct device_attribute *attr, char *buf)
++{
++	const struct gpio_desc	*desc = dev_get_drvdata(dev);
++	ssize_t			status;
++
++	mutex_lock(&sysfs_lock);
++
++	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
++		status = -EIO;
++	} else {
++		if (test_bit(FLAG_PULLUP, &desc->flags))
++			status = sprintf(buf, "pullup\n");
++		else if (test_bit(FLAG_PULLDOWN, &desc->flags))
++			status = sprintf(buf, "pulldown\n");
++		else if (test_bit(FLAG_STRONG, &desc->flags))
++			status = sprintf(buf, "strong\n");
++		else if (test_bit(FLAG_HIZ, &desc->flags))
++			status = sprintf(buf, "hiz\n");
++		else
++			status = -EINVAL;
++	}
++
++	mutex_unlock(&sysfs_lock);
++	return status;
++}
++
++static ssize_t gpio_drive_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t size)
++{
++	struct gpio_desc	*desc = dev_get_drvdata(dev);
++	ssize_t			status;
++
++	mutex_lock(&sysfs_lock);
++
++	if (!test_bit(FLAG_EXPORT, &desc->flags))
++		status = -EIO;
++	else {
++		clear_bit(FLAG_PULLUP, &desc->flags);
++		clear_bit(FLAG_PULLDOWN, &desc->flags);
++		clear_bit(FLAG_STRONG, &desc->flags);
++		clear_bit(FLAG_HIZ, &desc->flags);
++		if (sysfs_streq(buf, "pullup")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_PULLUP);
++			if (!status) {
++				set_bit(FLAG_PULLUP, &desc->flags);
++			}
++		} else if (sysfs_streq(buf, "pulldown")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_PULLDOWN);
++			if (!status) {
++				set_bit(FLAG_PULLDOWN, &desc->flags);
++			}
++		} else if (sysfs_streq(buf, "strong")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_STRONG);
++			if (!status) {
++				set_bit(FLAG_STRONG, &desc->flags);
++			}
++		} else if (sysfs_streq(buf, "hiz")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_HIZ);
++			if (!status) {
++				set_bit(FLAG_HIZ, &desc->flags);
++			}
++		} else {
++			status = -EINVAL;
++		}
++	}
++
++	mutex_unlock(&sysfs_lock);
++	return status ? : size;
++}
++
++static DEVICE_ATTR(drive, 0644,
++		gpio_drive_show, gpio_drive_store);
++
++
+ static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
+ 			       int n)
+ {
+@@ -377,6 +454,7 @@ static struct attribute *gpio_attrs[] = {
+ 	&dev_attr_edge.attr,
+ 	&dev_attr_value.attr,
+ 	&dev_attr_active_low.attr,
++	&dev_attr_drive.attr,
+ 	NULL,
+ };
+ 
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index 827510dbba30..d19928b9a311 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1315,6 +1315,23 @@ int gpiod_is_active_low(const struct gpio_desc *desc)
+ }
+ EXPORT_SYMBOL_GPL(gpiod_is_active_low);
+ 
++int gpiod_set_drive(struct gpio_desc *desc, unsigned mode)
++{
++	struct gpio_chip	*chip;
++
++	chip = desc->chip;
++	if (!chip || !chip->set || !chip->set_drive)
++		goto fail;
++
++	might_sleep_if(chip->can_sleep);
++
++	return chip->set_drive(chip, gpio_chip_hwgpio(desc), mode);
++
++fail:
++	return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(gpiod_set_drive);
++
+ /* I/O calls are only valid after configuration completed; the relevant
+  * "is this a valid GPIO" error checks should already have been done.
+  *
+diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
+index 07541c5670e6..cfa7406b10fd 100644
+--- a/drivers/gpio/gpiolib.h
++++ b/drivers/gpio/gpiolib.h
+@@ -96,6 +96,10 @@ struct gpio_desc {
+ #define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */
+ #define FLAG_USED_AS_IRQ 9	/* GPIO is connected to an IRQ */
+ #define FLAG_IS_HOGGED	11	/* GPIO is hogged */
++#define FLAG_PULLUP	12	/* Gpio drive is resistive pullup */
++#define FLAG_PULLDOWN	13	/* Gpio drive is resistive pulldown */
++#define FLAG_STRONG	14	/* Gpio drive is strong (fast output) */
++#define FLAG_HIZ	15	/* Gpio drive is Hi-Z (input) */
+ 
+ 	/* Connection label */
+ 	const char		*label;
+diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
+index 40ec1433f05d..519e8d458878 100644
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -76,6 +76,11 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+ 	return gpiod_set_debounce(gpio_to_desc(gpio), debounce);
+ }
+ 
++static inline int gpio_set_drive(unsigned gpio, unsigned mode)
++{
++	return gpiod_set_drive(gpio_to_desc(gpio), mode);
++}
++
+ static inline int gpio_get_value_cansleep(unsigned gpio)
+ {
+ 	return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio));
+diff --git a/include/linux/gpio.h b/include/linux/gpio.h
+index d12b5d566e4b..344e62d27700 100644
+--- a/include/linux/gpio.h
++++ b/include/linux/gpio.h
+@@ -30,6 +30,11 @@
+ #define GPIOF_EXPORT_DIR_FIXED	(GPIOF_EXPORT)
+ #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
+ 
++#define GPIOF_DRIVE_PULLUP	(1 << 7)
++#define GPIOF_DRIVE_PULLDOWN	(1 << 8)
++#define GPIOF_DRIVE_STRONG	(1 << 9)
++#define GPIOF_DRIVE_HIZ		(1 << 10)
++
+ /**
+  * struct gpio - a structure describing a GPIO with configuration
+  * @gpio:	the GPIO number
+@@ -148,6 +153,11 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+ 	return -ENOSYS;
+ }
+ 
++static inline int gpio_set_drive(unsigned gpio, unsigned mode)
++{
++	return -ENOSYS;
++}
++
+ static inline int gpio_get_value(unsigned gpio)
+ {
+ 	/* GPIO can never have been requested or set as {in,out}put */
+diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
+index fb0fde686cb1..17f5f187699b 100644
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -122,6 +122,8 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
+ 
+ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
+ 
++int gpiod_set_drive(struct gpio_desc *desc, unsigned mode);
++
+ int gpiod_is_active_low(const struct gpio_desc *desc);
+ int gpiod_cansleep(const struct gpio_desc *desc);
+ 
+@@ -376,6 +378,15 @@ static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
+ 	return -ENOSYS;
+ }
+ 
++
++static inline int gpiod_set_drive(unsigned gpio, unsigned mode)
++{
++	/* GPIO can never have been requested */
++	WARN_ON(1);
++	return -ENOSYS;
++}
++
++
+ static inline int gpiod_is_active_low(const struct gpio_desc *desc)
+ {
+ 	/* GPIO can never have been requested */
+diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
+index de502c7e4171..d59080ba9fec 100644
+--- a/include/linux/gpio/driver.h
++++ b/include/linux/gpio/driver.h
+@@ -116,6 +116,8 @@ struct gpio_chip {
+ 	int			(*set_debounce)(struct gpio_chip *chip,
+ 						unsigned offset,
+ 						unsigned debounce);
++	int			(*set_drive)(struct gpio_chip *chip,
++						unsigned offset, unsigned mode);
+ 
+ 	int			(*to_irq)(struct gpio_chip *chip,
+ 						unsigned offset);
+-- 
+2.16.4
+

+ 105 - 0
board/PSG/iot2000/linux-4.4-patches/0018-iot2000-hack-pwm-pca-9685-Provide-chip-level-pwm_per.patch

@@ -0,0 +1,105 @@
+From c25a8e605bcbb0ed2adde384587ffcfcf5783eef Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Fri, 17 Nov 2017 20:25:54 +0100
+Subject: [PATCH 18/18] iot2000-hack: pwm: pca-9685: Provide chip-level
+ pwm_period attribute
+
+Arduino runtime relies on this path to program the PWM period, rather
+than doing this via the upstream kernel API which is per channel.
+
+Another one not for upstream.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/pwm/pwm-pca9685.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+
+diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
+index 611b9263a896..ce765f903714 100644
+--- a/drivers/pwm/pwm-pca9685.c
++++ b/drivers/pwm/pwm-pca9685.c
+@@ -444,6 +444,54 @@ static const struct pwm_ops pca9685_pwm_ops = {
+ 	.owner = THIS_MODULE,
+ };
+ 
++static ssize_t pwm_period_show(struct device *parent,
++			       struct device_attribute *attr,
++			       char *buf)
++{
++	struct pwm_chip *chip = dev_get_drvdata(parent);
++
++	return sprintf(buf, "%u\n", to_pca(chip)->period_ns);
++}
++
++static ssize_t pwm_period_store(struct device *parent,
++				struct device_attribute *attr,
++				const char *buf, size_t size)
++{
++	struct pwm_chip *chip = dev_get_drvdata(parent);
++	struct pca9685 *pca = to_pca(chip);
++	int old_period_ns = pca->period_ns;
++	unsigned long long duty_scale, new_duty_ns;
++	unsigned int val, channel;
++	struct pwm_device *pwm;
++	int ret;
++
++	ret = kstrtouint(buf, 0, &val);
++	if (ret)
++		return ret;
++
++	for (channel = 0; channel < PCA9685_MAXCHAN; channel++) {
++		pwm = &chip->pwms[channel];
++
++		if (pca9685_pwm_is_gpio(pca, pwm))
++			continue;
++
++		/* Scale the rise time to maintain duty cycle */
++		duty_scale = val;
++		duty_scale *= 1000000;
++		do_div(duty_scale, old_period_ns);
++		new_duty_ns = duty_scale * pwm_get_duty_cycle(pwm);
++		do_div(new_duty_ns, 1000000);
++		/* Update the duty_cycle */
++		ret = pwm_config(pwm, (int)new_duty_ns, val);
++		if (ret)
++			return ret;
++	}
++
++	return size;
++}
++
++static DEVICE_ATTR_RW(pwm_period);
++
+ static const struct regmap_config pca9685_regmap_i2c_config = {
+ 	.reg_bits = 8,
+ 	.val_bits = 8,
+@@ -504,8 +552,17 @@ static int pca9685_pwm_probe(struct i2c_client *client,
+ 	if (ret < 0)
+ 		return ret;
+ 
++	ret = sysfs_create_file(&pca->chip.dev->kobj,
++				&dev_attr_pwm_period.attr);
++	if (ret < 0) {
++		pwmchip_remove(&pca->chip);
++		return ret;
++	}
++
+ 	ret = pca9685_pwm_gpio_probe(pca);
+ 	if (ret < 0) {
++		sysfs_remove_file(&pca->chip.dev->kobj,
++				  &dev_attr_pwm_period.attr);
+ 		pwmchip_remove(&pca->chip);
+ 		return ret;
+ 	}
+@@ -526,6 +583,8 @@ static int pca9685_pwm_remove(struct i2c_client *client)
+ 	struct pca9685 *pca = i2c_get_clientdata(client);
+ 	int ret;
+ 
++	sysfs_remove_file(&pca->chip.dev->kobj, &dev_attr_pwm_period.attr);
++
+ 	ret = pwmchip_remove(&pca->chip);
+ 	if (ret)
+ 		return ret;
+-- 
+2.16.4
+

+ 39 - 0
board/PSG/iot2000/linux-4.4-patches/rt-0001-spi-pca2xx-pci-Allow-MSI.patch

@@ -0,0 +1,39 @@
+From 2fb20a434404d954740556b56466365587c33cfc Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Mon, 26 Sep 2016 08:52:49 +0200
+Subject: [PATCH 1/2] spi: pca2xx-pci: Allow MSI
+
+Backport of 64e02cb0bdfc7cef0a01e2ad4d567fdc0a74450e upstream.
+
+Now that the core is ready for edge-triggered interrupts, we can safely
+allow the PCI versions that provide this to enable the feature and,
+thus, have less shared interrupts.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/spi/spi-pxa2xx-pci.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
+index ac0658ead1b9..0a9be3b6538a 100644
+--- a/drivers/spi/spi-pxa2xx-pci.c
++++ b/drivers/spi/spi-pxa2xx-pci.c
+@@ -156,10 +156,14 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
+ 		dev_err(&dev->dev, "failed to ioremap() registers\n");
+ 		return -EIO;
+ 	}
+-	ssp->irq = dev->irq;
+ 	ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn;
+ 	ssp->type = c->type;
+ 
++	pci_set_master(dev);
++
++	pci_enable_msi(dev);
++	ssp->irq = dev->irq;
++
+ 	snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id);
+ 	ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL,
+ 					CLK_IS_ROOT, c->max_clk_rate);
+-- 
+2.13.6
+

+ 52 - 0
board/PSG/iot2000/linux-4.4-patches/rt-0002-gpio-dwapb-Work-around-RT-full-s-enforced-IRQ-thread.patch

@@ -0,0 +1,52 @@
+From 162379965182fa0cdd447ac462c3f3b8fb7377d8 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Wed, 3 Jan 2018 15:32:56 +0100
+Subject: [PATCH 2/2] gpio: dwapb: Work around RT-full's enforced IRQ threading
+ side effects
+
+Under RT-full, dwapb_irq_handler will run in a threaded IRQ. However,
+generic_handle_irq expect us to call it with IRQs disabled.
+Documentation/gpio/driver.txt suggest to use fake raw spinlock around
+generic_handle_irq in order to call the latter with interrupts off.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpio-dwapb.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
+index fcd5b0acfc72..dad75d594f76 100644
+--- a/drivers/gpio/gpio-dwapb.c
++++ b/drivers/gpio/gpio-dwapb.c
+@@ -81,6 +81,7 @@ struct dwapb_gpio {
+ 	struct dwapb_gpio_port	*ports;
+ 	unsigned int		nr_ports;
+ 	struct irq_domain	*domain;
++	raw_spinlock_t		wa_rt_lock;
+ };
+ 
+ static inline struct dwapb_gpio_port *
+@@ -135,8 +136,11 @@ static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
+ 	while (irq_status) {
+ 		int hwirq = fls(irq_status) - 1;
+ 		int gpio_irq = irq_find_mapping(gpio->domain, hwirq);
++		unsigned long wa_flags;
+ 
++		raw_spin_lock_irqsave(&gpio->wa_rt_lock, wa_flags);
+ 		generic_handle_irq(gpio_irq);
++		raw_spin_unlock_irqrestore(&gpio->wa_rt_lock, wa_flags);
+ 		irq_status &= ~BIT(hwirq);
+ 
+ 		if ((irq_get_trigger_type(gpio_irq) & IRQ_TYPE_SENSE_MASK)
+@@ -541,6 +545,8 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
+ 	if (!gpio)
+ 		return -ENOMEM;
+ 
++	raw_spin_lock_init(&gpio->wa_rt_lock);
++
+ 	gpio->dev = &pdev->dev;
+ 	gpio->nr_ports = pdata->nports;
+ 
+-- 
+2.13.6
+

+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0001-stmmac-Add-support-for-SIMATIC-IOT2000-platform.patch → board/PSG/iot2000/linux-4.4-patches_orig/0001-stmmac-Add-support-for-SIMATIC-IOT2000-platform.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0002-serial-uapi-Add-support-for-bus-termination.patch → board/PSG/iot2000/linux-4.4-patches_orig/0002-serial-uapi-Add-support-for-bus-termination.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0003-serial-8250_pci-Use-symbolic-constants-for-EXAR-s-MP.patch → board/PSG/iot2000/linux-4.4-patches_orig/0003-serial-8250_pci-Use-symbolic-constants-for-EXAR-s-MP.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0004-serial-8250_pci-Fix-EXAR-feature-control-register-co.patch → board/PSG/iot2000/linux-4.4-patches_orig/0004-serial-8250_pci-Fix-EXAR-feature-control-register-co.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0005-serial-8250_pci-Add-support-for-IOT2000-platform.patch → board/PSG/iot2000/linux-4.4-patches_orig/0005-serial-8250_pci-Add-support-for-IOT2000-platform.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0006-serial-8250_pci-Add-support-for-red-user-LED-on-IOT2.patch → board/PSG/iot2000/linux-4.4-patches_orig/0006-serial-8250_pci-Add-support-for-red-user-LED-on-IOT2.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0007-spi-pxa2xx-Factor-out-handle_bad_msg.patch → board/PSG/iot2000/linux-4.4-patches_orig/0007-spi-pxa2xx-Factor-out-handle_bad_msg.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0008-spi-pxa2xx-Prepare-for-edge-triggered-interrupts.patch → board/PSG/iot2000/linux-4.4-patches_orig/0008-spi-pxa2xx-Prepare-for-edge-triggered-interrupts.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0009-spi-pca2xx-pci-Allow-MSI.patch → board/PSG/iot2000/linux-4.4-patches_orig/0009-spi-pca2xx-pci-Allow-MSI.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0010-efi-Move-efi_status_to_err-to-drivers-firmware-efi.patch → board/PSG/iot2000/linux-4.4-patches_orig/0010-efi-Move-efi_status_to_err-to-drivers-firmware-efi.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0011-efi-Add-capsule-update-support.patch → board/PSG/iot2000/linux-4.4-patches_orig/0011-efi-Add-capsule-update-support.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0012-x86-efi-Force-EFI-reboot-to-process-pending-capsules.patch → board/PSG/iot2000/linux-4.4-patches_orig/0012-x86-efi-Force-EFI-reboot-to-process-pending-capsules.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0013-efi-Add-misc-char-driver-interface-to-update-EFI-fir.patch → board/PSG/iot2000/linux-4.4-patches_orig/0013-efi-Add-misc-char-driver-interface-to-update-EFI-fir.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0014-efi-capsule-Make-efi_capsule_pending-lockless.patch → board/PSG/iot2000/linux-4.4-patches_orig/0014-efi-capsule-Make-efi_capsule_pending-lockless.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0015-efi-capsule-Move-capsule-to-the-stack-in-efi_capsule.patch → board/PSG/iot2000/linux-4.4-patches_orig/0015-efi-capsule-Move-capsule-to-the-stack-in-efi_capsule.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0016-efi-capsule-Allocate-whole-capsule-into-virtual-memo.patch → board/PSG/iot2000/linux-4.4-patches_orig/0016-efi-capsule-Allocate-whole-capsule-into-virtual-memo.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0017-efi-capsule-Fix-return-code-on-failing-kmap-vmap.patch → board/PSG/iot2000/linux-4.4-patches_orig/0017-efi-capsule-Fix-return-code-on-failing-kmap-vmap.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0018-efi-capsule-Remove-pr_debug-on-ENOMEM-or-EFAULT.patch → board/PSG/iot2000/linux-4.4-patches_orig/0018-efi-capsule-Remove-pr_debug-on-ENOMEM-or-EFAULT.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0019-efi-capsule-Clean-up-pr_err-info-messages.patch → board/PSG/iot2000/linux-4.4-patches_orig/0019-efi-capsule-Clean-up-pr_err-info-messages.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0020-efi-capsule-Adjust-return-type-of-efi_capsule_setup_.patch → board/PSG/iot2000/linux-4.4-patches_orig/0020-efi-capsule-Adjust-return-type-of-efi_capsule_setup_.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0021-efi-capsule-loader-Use-a-cached-copy-of-the-capsule-.patch → board/PSG/iot2000/linux-4.4-patches_orig/0021-efi-capsule-loader-Use-a-cached-copy-of-the-capsule-.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0022-efi-capsule-loader-Redirect-calls-to-efi_capsule_set.patch → board/PSG/iot2000/linux-4.4-patches_orig/0022-efi-capsule-loader-Redirect-calls-to-efi_capsule_set.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0023-efi-capsule-loader-Use-page-addresses-rather-than-st.patch → board/PSG/iot2000/linux-4.4-patches_orig/0023-efi-capsule-loader-Use-page-addresses-rather-than-st.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0024-efi-capsule-Add-support-for-Quark-security-header.patch → board/PSG/iot2000/linux-4.4-patches_orig/0024-efi-capsule-Add-support-for-Quark-security-header.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0025-mfd-intel_quark_i2c_gpio-Use-dmi_system_id-table-for.patch → board/PSG/iot2000/linux-4.4-patches_orig/0025-mfd-intel_quark_i2c_gpio-Use-dmi_system_id-table-for.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0026-mfd-intel_quark_i2c_gpio-Add-support-for-SIMATIC-IOT.patch → board/PSG/iot2000/linux-4.4-patches_orig/0026-mfd-intel_quark_i2c_gpio-Add-support-for-SIMATIC-IOT.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0027-iot2000-hack-Work-around-DSDT-mistake.patch → board/PSG/iot2000/linux-4.4-patches_orig/0027-iot2000-hack-Work-around-DSDT-mistake.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0028-gpio-pca953x-provide-GPIO-base-based-on-_UID.patch → board/PSG/iot2000/linux-4.4-patches_orig/0028-gpio-pca953x-provide-GPIO-base-based-on-_UID.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0029-staging-iio-add-support-for-ADC1x8s102.patch → board/PSG/iot2000/linux-4.4-patches_orig/0029-staging-iio-add-support-for-ADC1x8s102.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0030-adc1x8s102-support-ACPI-based-enumeration.patch → board/PSG/iot2000/linux-4.4-patches_orig/0030-adc1x8s102-support-ACPI-based-enumeration.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0031-gpio-pca953x-add-drive-property.patch → board/PSG/iot2000/linux-4.4-patches_orig/0031-gpio-pca953x-add-drive-property.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0032-pca9685-PCA9685-PWM-and-GPIO-multi-function-device.patch → board/PSG/iot2000/linux-4.4-patches_orig/0032-pca9685-PCA9685-PWM-and-GPIO-multi-function-device.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0033-spi-pxa2xx-fixed-ACPI-based-enumeration-of-SPI-devic.patch → board/PSG/iot2000/linux-4.4-patches_orig/0033-spi-pxa2xx-fixed-ACPI-based-enumeration-of-SPI-devic.patch


+ 0 - 0
board/PSG/iot2000/linux-4.4-patches/0034-acpi-added-a-custom-DSDT-file.patch → board/PSG/iot2000/linux-4.4-patches_orig/0034-acpi-added-a-custom-DSDT-file.patch


+ 3 - 3
configs/iot2000_defconfig

@@ -26,9 +26,8 @@ BR2_ROOTFS_OVERLAY="../PSG/board/PSG/iot2000/rootfs_overlay"
 BR2_ROOTFS_POST_BUILD_SCRIPT="../PSG/board/PSG/iot2000/post-build.sh"
 BR2_ROOTFS_POST_IMAGE_SCRIPT="../PSG/board/PSG/iot2000/post-image.sh"
 BR2_LINUX_KERNEL=y
-BR2_LINUX_KERNEL_CUSTOM_GIT=y
-BR2_LINUX_KERNEL_CUSTOM_REPO_URL="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git"
-BR2_LINUX_KERNEL_CUSTOM_REPO_VERSION="linux-4.4.y"
+BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
+BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="https://git.kernel.org/pub/scm/linux/kernel/git/cip/linux-cip.git/snapshot/linux-cip-4.4.185-cip35.tar.gz"
 BR2_LINUX_KERNEL_PATCH="../PSG/board/PSG/iot2000/linux-4.4-patches"
 BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
 BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="../PSG/board/PSG/iot2000/linux-4.4.config"
@@ -230,6 +229,7 @@ BR2_PACKAGE_SUDO=y
 BR2_PACKAGE_TIME=y
 BR2_PACKAGE_HTOP=y
 BR2_PACKAGE_KEYUTILS=y
+BR2_PACKAGE_NUMACTL=y
 BR2_PACKAGE_UTIL_LINUX_LOGGER=y
 BR2_PACKAGE_UTIL_LINUX_RFKILL=y
 BR2_PACKAGE_UTIL_LINUX_SETTERM=y