From: "Chai, Chong Yi" <chong.yi.c...@intel.com>

---
 features/soc/baytrail/baytrail.scc                 |  10 +
 ...esignware-I2C-to-be-probed-before-SMBus-f.patch |  54 ++++
 ...i2c-designware-Fix-checkpatch.pl-warnings.patch |  51 ++++
 ...i2c-designware-add-i2c-high-speed-support.patch | 234 +++++++++++++++
 ...are-add-per-channel-speed-parameter-and-f.patch | 331 +++++++++++++++++++++
 .../i2c-designware-cleanup-__i2c_dw_enable.patch   |  54 ++++
 ...2c-designware-cleanup-irq-handler-setting.patch |  53 ++++
 ...are-explicitly-abort-running-operation-on.patch |  70 +++++
 .../i2c-designware-improve-FIFO-performance.patch  | 137 +++++++++
 ...are-use-hardware-provided-Rx-Tx-FIFO-dept.patch | 220 ++++++++++++++
 ...nware-use-symbolic-names-for-command-bits.patch |  50 ++++
 11 files changed, 1264 insertions(+)
 create mode 100644 
features/soc/baytrail/i2c-allow-Designware-I2C-to-be-probed-before-SMBus-f.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-Fix-checkpatch.pl-warnings.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-add-i2c-high-speed-support.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-add-per-channel-speed-parameter-and-f.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-cleanup-__i2c_dw_enable.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-cleanup-irq-handler-setting.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-explicitly-abort-running-operation-on.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-improve-FIFO-performance.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-use-hardware-provided-Rx-Tx-FIFO-dept.patch
 create mode 100644 
features/soc/baytrail/i2c-designware-use-symbolic-names-for-command-bits.patch

diff --git a/features/soc/baytrail/baytrail.scc 
b/features/soc/baytrail/baytrail.scc
index b1638a1..1e7c7f2 100644
--- a/features/soc/baytrail/baytrail.scc
+++ b/features/soc/baytrail/baytrail.scc
@@ -17,3 +17,13 @@ patch 
usb-dwc3-core-Fix-gadget-for-system-suspend-resume.patch
 patch usb-xhci-Change-how-we-indicate-a-host-supports-Link.patch
 patch usb-core-hub-Generate-uevent-for-overcurrent-event.patch
 patch usb-core-hub-Fix-checkpatch.pl-error.patch
+patch i2c-allow-Designware-I2C-to-be-probed-before-SMBus-f.patch
+patch i2c-designware-cleanup-irq-handler-setting.patch
+patch i2c-designware-use-hardware-provided-Rx-Tx-FIFO-dept.patch
+patch i2c-designware-use-symbolic-names-for-command-bits.patch
+patch i2c-designware-cleanup-__i2c_dw_enable.patch
+patch i2c-designware-explicitly-abort-running-operation-on.patch
+patch i2c-designware-improve-FIFO-performance.patch
+patch i2c-designware-add-per-channel-speed-parameter-and-f.patch
+patch i2c-designware-add-i2c-high-speed-support.patch
+patch i2c-designware-Fix-checkpatch.pl-warnings.patch
diff --git 
a/features/soc/baytrail/i2c-allow-Designware-I2C-to-be-probed-before-SMBus-f.patch
 
b/features/soc/baytrail/i2c-allow-Designware-I2C-to-be-probed-before-SMBus-f.patch
new file mode 100644
index 0000000..5c26d2d
--- /dev/null
+++ 
b/features/soc/baytrail/i2c-allow-Designware-I2C-to-be-probed-before-SMBus-f.patch
@@ -0,0 +1,54 @@
+From aca3cf92cab6182363a365ac9d7987398c662d2b Mon Sep 17 00:00:00 2001
+From: Maurice Petallo <mauricex.r.peta...@intel.com>
+Date: Tue, 17 Feb 2015 13:21:01 +0800
+Subject: [PATCH 042/164] i2c: allow Designware I2C to be probed before SMBus
+ for Baytrail
+
+When SMBus is enabled in Baytrail, it is being probed first before
+all the Designware I2C devices. This means SMBus will take the first
+available bus id which is 0 and then the I2C devices will take the
+next succeeding bus ids. This should be fine as long as the I2C
+devices bus ids are assigned dynamically.
+
+The problem arises when the I2C devices' bus ids are assigned
+statically and the SMBus is probed first. The kernel will fail to
+add the i2c adapter because something else, which in that case is
+the SMBus, has taken the bus id that the i2c adapter is trying to
+take.
+
+As mentioned in commit "i2c: designware-pci: use static bus num
+allocation for baytrail", it is required for I2C devices' bus ids
+to be assigned statically for LPE Audio to register the i2c properly.
+
+To resolve this, we either force the SMBus to take the next bus id
+after all the designware I2C devices or we allow all the I2C devices
+to be probed first before the SMBus. This patch implements the 2nd.
+
+Signed-off-by: Maurice Petallo <mauricex.r.peta...@intel.com>
+---
+ drivers/i2c/busses/Makefile |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index a08931f..26c50ea 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -12,7 +12,6 @@ obj-$(CONFIG_I2C_ALI15X3)    += i2c-ali15x3.o
+ obj-$(CONFIG_I2C_AMD756)      += i2c-amd756.o
+ obj-$(CONFIG_I2C_AMD756_S4882)        += i2c-amd756-s4882.o
+ obj-$(CONFIG_I2C_AMD8111)     += i2c-amd8111.o
+-obj-$(CONFIG_I2C_I801)                += i2c-i801.o
+ obj-$(CONFIG_I2C_ISCH)                += i2c-isch.o
+ obj-$(CONFIG_I2C_ISMT)                += i2c-ismt.o
+ obj-$(CONFIG_I2C_NFORCE2)     += i2c-nforce2.o
+@@ -41,6 +40,7 @@ obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)        += 
i2c-designware-platform.o
+ i2c-designware-platform-objs := i2c-designware-platdrv.o
+ obj-$(CONFIG_I2C_DESIGNWARE_PCI)      += i2c-designware-pci.o
+ i2c-designware-pci-objs := i2c-designware-pcidrv.o
++obj-$(CONFIG_I2C_I801)                += i2c-i801.o
+ obj-$(CONFIG_I2C_EG20T)               += i2c-eg20t.o
+ obj-$(CONFIG_I2C_EXYNOS5)     += i2c-exynos5.o
+ obj-$(CONFIG_I2C_GPIO)                += i2c-gpio.o
+-- 
+1.7.7.6
+
diff --git 
a/features/soc/baytrail/i2c-designware-Fix-checkpatch.pl-warnings.patch 
b/features/soc/baytrail/i2c-designware-Fix-checkpatch.pl-warnings.patch
new file mode 100644
index 0000000..80effb4
--- /dev/null
+++ b/features/soc/baytrail/i2c-designware-Fix-checkpatch.pl-warnings.patch
@@ -0,0 +1,51 @@
+From 9f827d6746c3231a2e6c2a6f2a17fb371443cd2a Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Fri, 21 Aug 2015 12:21:20 +0800
+Subject: [PATCH 155/164] i2c: designware: Fix checkpatch.pl warnings
+
+This commit is to fix the result of running scripts/checkpatch.pl against
+0127-i2c-designware-add-per-channel-speed-parameter-and-f.patch
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-pcidrv.c  |    2 +-
+ drivers/i2c/busses/i2c-designware-platdrv.c |    6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index 2c22aef..c52028f 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -339,7 +339,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+       u32 mode;
+       struct  dw_pci_controller *controller;
+       struct dw_scl_sda_cfg *cfg;
+-      static int channel = 0;
++      static int channel;
+ 
+       if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+               dev_err(&pdev->dev, "%s: invalid driver data %ld\n", __func__,
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
+index 084d6ec..e7a4214 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -95,13 +95,13 @@ static void i2c_dw_parse_flags(char *flags)
+                       i++; /* next channel */
+                       break;
+               default:
+-                      pr_err("i2c-designware-platform: invalid "
+-                             "flag %c for channel %d\n", *p, i);
++                      pr_err("i2c-designware-platform: invalid flag %c for 
channel %d\n",
++                              *p, i);
+               }
+       }
+ }
+ 
+-static int channel = 0;
++static int channel;
+ 
+ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+ {
+-- 
+1.7.7.6
+
diff --git 
a/features/soc/baytrail/i2c-designware-add-i2c-high-speed-support.patch 
b/features/soc/baytrail/i2c-designware-add-i2c-high-speed-support.patch
new file mode 100644
index 0000000..e27076d
--- /dev/null
+++ b/features/soc/baytrail/i2c-designware-add-i2c-high-speed-support.patch
@@ -0,0 +1,234 @@
+From e1cd14a14f6584985c3a27f69f220b4569364380 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:15:01 +0800
+Subject: [PATCH 128/164] i2c: designware: add i2c high-speed support
+
+This patch enable the High-speed mode.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-core.c    |   23 +++++++++++++++++++++++
+ drivers/i2c/busses/i2c-designware-core.h    |    6 ++++++
+ drivers/i2c/busses/i2c-designware-pcidrv.c  |   18 ++++++++++++++++--
+ drivers/i2c/busses/i2c-designware-platdrv.c |   23 +++++++++++++++++++++--
+ 4 files changed, 66 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
+index c359775..2bf62db 100644
+--- a/drivers/i2c/busses/i2c-designware-core.c
++++ b/drivers/i2c/busses/i2c-designware-core.c
+@@ -41,6 +41,7 @@
+  */
+ #define DW_IC_CON             0x0
+ #define DW_IC_TAR             0x4
++# define DW_IC_TAR_HS_MASTER  (BIT(10) | BIT(11))
+ #define DW_IC_DATA_CMD                0x10
+ # define DW_IC_CMD_READ               BIT(8)
+ # define DW_IC_CMD_STOP               BIT(9)
+@@ -49,6 +50,8 @@
+ #define DW_IC_SS_SCL_LCNT     0x18
+ #define DW_IC_FS_SCL_HCNT     0x1c
+ #define DW_IC_FS_SCL_LCNT     0x20
++#define DW_IC_HS_SCL_HCNT     0x24
++#define DW_IC_HS_SCL_LCNT     0x28
+ #define DW_IC_INTR_STAT               0x2c
+ #define DW_IC_INTR_MASK               0x30
+ #define DW_IC_RAW_INTR_STAT   0x34
+@@ -372,6 +375,23 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
+       dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
+       dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+ 
++      if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
++          DW_IC_CON_SPEED_HIGH) {
++              if (((comp_param1 >> 2) & 3) != 3) {
++                      dev_err(dev->dev, "High Speed not supported!\n");
++                      dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
++                      dev->master_cfg |= DW_IC_CON_SPEED_FAST;
++                      dev->high_speed = false;
++              } else if (dev->hs_hcnt && dev->hs_lcnt) {
++                      hcnt = dev->hs_hcnt;
++                      lcnt = dev->hs_lcnt;
++                      dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
++                      dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
++                      dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
++                              hcnt, lcnt);
++              }
++      }
++
+       /* Configure SDA Hold Time if required */
+       if (dev->sda_hold_time) {
+               reg = dw_readl(dev, DW_IC_COMP_VERSION);
+@@ -438,6 +458,9 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
+               ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+       }
+ 
++      if (dev->high_speed) /* High speed */
++              ic_tar |= DW_IC_TAR_HS_MASTER; /* Send master highspeed addr */
++
+       dw_writel(dev, ic_con, DW_IC_CON);
+ 
+       /*
+diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
+index 956641f..5bbe769 100644
+--- a/drivers/i2c/busses/i2c-designware-core.h
++++ b/drivers/i2c/busses/i2c-designware-core.h
+@@ -31,6 +31,7 @@
+ #define DW_IC_CON_SPEED_MASK          0x6
+ #define DW_IC_CON_SPEED_STD           0x2
+ #define DW_IC_CON_SPEED_FAST          0x4
++#define DW_IC_CON_SPEED_HIGH          0x6
+ #define DW_IC_CON_10BITADDR_MASTER    0x10
+ #define DW_IC_CON_RESTART_EN          0x20
+ #define DW_IC_CON_SLAVE_DISABLE               0x40
+@@ -66,6 +67,8 @@
+  * @ss_lcnt: standard speed LCNT value
+  * @fs_hcnt: fast speed HCNT value
+  * @fs_lcnt: fast speed LCNT value
++ * @hs_hcnt: high speed HCNT value
++ * @hs_lcnt: high speed LCNT value
+  *
+  * HCNT and LCNT parameters can be used if the platform knows more accurate
+  * values than the one computed based only on the input clock frequency.
+@@ -104,6 +107,9 @@ struct dw_i2c_dev {
+       u16                     ss_lcnt;
+       u16                     fs_hcnt;
+       u16                     fs_lcnt;
++      u16                     hs_hcnt;
++      u16                     hs_lcnt;
++      bool                    high_speed;
+ };
+ 
+ #define ACCESS_SWAP           0x00000001
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index 0332baf..2c22aef 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -45,10 +45,11 @@
+ 
+ static char *flags;
+ module_param(flags, charp, 0444);
+-MODULE_PARM_DESC(flags, "colon-delimited per-channel flags: [sfp]\n"
++MODULE_PARM_DESC(flags, "colon-delimited per-channel flags: [sfph]\n"
+ "     s - standard speed (100KHz)\n"
+ "     f - fast speed (400KHz)\n"
+-"     p - fast-plus speed (1000kHz)\n");
++"     p - fast-plus speed (1000kHz)\n"
++"     h - high speed (3.4MHz)\n");
+ 
+ #define MAX_CHANNELS  7
+ 
+@@ -57,6 +58,7 @@ enum i2c_speeds {
+       i2c_ss,
+       i2c_fs,
+       i2c_fplus,
++      i2c_hs
+ };
+ 
+ static struct chan_opts {
+@@ -91,6 +93,8 @@ struct dw_scl_sda_cfg {
+       u32 fs_lcnt;
+       u32 fp_hcnt;
+       u32 fp_lcnt;
++      u32 hs_hcnt;
++      u32 hs_lcnt;
+       u32 sda_hold;
+ };
+ 
+@@ -120,6 +124,8 @@ static struct dw_scl_sda_cfg byt_config = {
+       .fs_lcnt = 0x99,
+       .fp_hcnt = 0x1B,
+       .fp_lcnt = 0x3A,
++      .hs_hcnt = 0x06,
++      .hs_lcnt = 0x0C,
+       .sda_hold = 0x6,
+ };
+ 
+@@ -242,6 +248,9 @@ static void i2c_dw_parse_flags(char *flags)
+               case 'p':
+                       chan_opts[i].speed = i2c_fplus;
+                       break;
++              case 'h':
++                      chan_opts[i].speed = i2c_hs;
++                      break;
+               case ':':
+                       i++; /* next channel */
+                       break;
+@@ -378,6 +387,9 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+       } else if (chan_opts[channel].speed == i2c_fs ||
+                  chan_opts[channel].speed == i2c_fplus) {
+               mode = DW_IC_CON_SPEED_FAST;
++      } else if (chan_opts[channel].speed == i2c_hs) {
++              dev->high_speed = true;
++              mode = DW_IC_CON_SPEED_HIGH;
+       } else { /* speed not set - using default from dw_pci_controller */
+               mode = controller->bus_cfg & DW_IC_CON_SPEED_MASK;
+       }
+@@ -394,6 +406,8 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+                       dev->fs_hcnt = cfg->fs_hcnt;
+                       dev->fs_lcnt = cfg->fs_lcnt;
+               }
++              dev->hs_hcnt = cfg->hs_hcnt;
++              dev->hs_lcnt = cfg->hs_lcnt;
+               dev->sda_hold_time = cfg->sda_hold;
+       }
+ 
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
+index 530b9d1..084d6ec 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -45,10 +45,11 @@
+ 
+ static char *flags;
+ module_param(flags, charp, 0444);
+-MODULE_PARM_DESC(flags, "colon-delimited per-channel flags: [sfp]\n"
++MODULE_PARM_DESC(flags, "colon-delimited per-channel flags: [sfph]\n"
+ "     s - standard speed (100KHz)\n"
+ "     f - fast speed (400KHz)\n"
+-"     p - fast-plus speed (1000kHz)\n");
++"     p - fast-plus speed (1000kHz)\n"
++"     h - high speed (3.4MHz)\n");
+ 
+ #define MAX_CHANNELS  7
+ 
+@@ -57,6 +58,7 @@ enum i2c_speeds {
+       i2c_ss,
+       i2c_fs,
+       i2c_fplus,
++      i2c_hs
+ };
+ 
+ static struct chan_opts {
+@@ -86,6 +88,9 @@ static void i2c_dw_parse_flags(char *flags)
+               case 'p':
+                       chan_opts[i].speed = i2c_fplus;
+                       break;
++              case 'h':
++                      chan_opts[i].speed = i2c_hs;
++                      break;
+               case ':':
+                       i++; /* next channel */
+                       break;
+@@ -229,6 +234,20 @@ static int dw_i2c_probe(struct platform_device *pdev)
+       } else if (chan_opts[channel].speed == i2c_fs ||
+               chan_opts[channel].speed == i2c_fplus) {
+               dev->master_cfg |= DW_IC_CON_SPEED_FAST;
++      } else if (chan_opts[channel].speed == i2c_hs) {
++              u32 ic_clk = dev->get_clk_rate_khz(dev);
++              u32 hs_hcnt, hs_lcnt;
++              hs_hcnt = (60 * ic_clk) / 1000000;
++              hs_lcnt = (120 * ic_clk) / 1000000;
++              if (hs_hcnt < 2) {
++                      dev_warn(dev->dev, "Clock rate too low for high 
speed!\n");
++                      dev->master_cfg |= DW_IC_CON_SPEED_FAST;
++              } else {
++                      dev->hs_hcnt = hs_hcnt;
++                      dev->hs_lcnt = hs_lcnt;
++                      dev->master_cfg |= DW_IC_CON_SPEED_HIGH;
++                      dev->high_speed = true;
++              }
+       } else {
+               dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+       }
+-- 
+1.7.7.6
+
diff --git 
a/features/soc/baytrail/i2c-designware-add-per-channel-speed-parameter-and-f.patch
 
b/features/soc/baytrail/i2c-designware-add-per-channel-speed-parameter-and-f.patch
new file mode 100644
index 0000000..410f3f9
--- /dev/null
+++ 
b/features/soc/baytrail/i2c-designware-add-per-channel-speed-parameter-and-f.patch
@@ -0,0 +1,331 @@
+From a6fae535b3d2d6a1a4997d69f2a7fefe4ed84bcf Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:14:53 +0800
+Subject: [PATCH 127/164] i2c: designware: add per-channel speed parameter and
+ fast-plus speed option
+
+This patch allows the I2C transfer speed to be configured via module
+parameter for each channel available.
+
+This patch also enable the Fast-mode Plus.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-core.h    |    1 +
+ drivers/i2c/busses/i2c-designware-pcidrv.c  |  100 +++++++++++++++++++++++++-
+ drivers/i2c/busses/i2c-designware-platdrv.c |   82 ++++++++++++++++++++--
+ 3 files changed, 174 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
+index e59dc2c..956641f 100644
+--- a/drivers/i2c/busses/i2c-designware-core.h
++++ b/drivers/i2c/busses/i2c-designware-core.h
+@@ -28,6 +28,7 @@
+ 
+ 
+ #define DW_IC_CON_MASTER              0x1
++#define DW_IC_CON_SPEED_MASK          0x6
+ #define DW_IC_CON_SPEED_STD           0x2
+ #define DW_IC_CON_SPEED_FAST          0x4
+ #define DW_IC_CON_10BITADDR_MASTER    0x10
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index c87f40c..0332baf 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -43,6 +43,26 @@
+ 
+ #define DRIVER_NAME "i2c-designware-pci"
+ 
++static char *flags;
++module_param(flags, charp, 0444);
++MODULE_PARM_DESC(flags, "colon-delimited per-channel flags: [sfp]\n"
++"     s - standard speed (100KHz)\n"
++"     f - fast speed (400KHz)\n"
++"     p - fast-plus speed (1000kHz)\n");
++
++#define MAX_CHANNELS  7
++
++enum i2c_speeds {
++      i2c_none = 0,
++      i2c_ss,
++      i2c_fs,
++      i2c_fplus,
++};
++
++static struct chan_opts {
++      enum i2c_speeds speed;
++} chan_opts[MAX_CHANNELS];
++
+ enum dw_pci_ctl_id_t {
+       moorestown_0,
+       moorestown_1,
+@@ -69,6 +89,8 @@ struct dw_scl_sda_cfg {
+       u32 fs_hcnt;
+       u32 ss_lcnt;
+       u32 fs_lcnt;
++      u32 fp_hcnt;
++      u32 fp_lcnt;
+       u32 sda_hold;
+ };
+ 
+@@ -96,6 +118,8 @@ static struct dw_scl_sda_cfg byt_config = {
+       .fs_hcnt = 0x55,
+       .ss_lcnt = 0x200,
+       .fs_lcnt = 0x99,
++      .fp_hcnt = 0x1B,
++      .fp_lcnt = 0x3A,
+       .sda_hold = 0x6,
+ };
+ 
+@@ -200,6 +224,34 @@ static struct i2c_algorithm i2c_dw_algo = {
+       .functionality  = i2c_dw_func,
+ };
+ 
++static void i2c_dw_parse_flags(char *flags)
++{
++      char *p = flags;
++      int i;
++
++      for (i = 0; i < MAX_CHANNELS; p++) {
++              if (!*p)
++                      break;
++              switch (*p) {
++              case 's':
++                      chan_opts[i].speed = i2c_ss;
++                      break;
++              case 'f':
++                      chan_opts[i].speed = i2c_fs;
++                      break;
++              case 'p':
++                      chan_opts[i].speed = i2c_fplus;
++                      break;
++              case ':':
++                      i++; /* next channel */
++                      break;
++              default:
++                      pr_err(DRIVER_NAME ": invalid flag %c for channel %d\n",
++                             *p, i);
++              }
++      }
++}
++
+ static int i2c_dw_pci_suspend(struct device *dev)
+ {
+       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+@@ -275,8 +327,10 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+       struct dw_i2c_dev *dev;
+       struct i2c_adapter *adap;
+       int r;
++      u32 mode;
+       struct  dw_pci_controller *controller;
+       struct dw_scl_sda_cfg *cfg;
++      static int channel = 0;
+ 
+       if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+               dev_err(&pdev->dev, "%s: invalid driver data %ld\n", __func__,
+@@ -313,13 +367,33 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+       dev->functionality = controller->functionality |
+                               DW_DEFAULT_FUNCTIONALITY;
+ 
+-      dev->master_cfg =  controller->bus_cfg;
++      if (channel >= MAX_CHANNELS) {
++              dev_warn(&pdev->dev, "Using default params\n");
++              channel = MAX_CHANNELS - 1;
++              memset(&chan_opts[channel], 0, sizeof(struct chan_opts));
++      }
++
++      if (chan_opts[channel].speed == i2c_ss) {
++              mode = DW_IC_CON_SPEED_STD;
++      } else if (chan_opts[channel].speed == i2c_fs ||
++                 chan_opts[channel].speed == i2c_fplus) {
++              mode = DW_IC_CON_SPEED_FAST;
++      } else { /* speed not set - using default from dw_pci_controller */
++              mode = controller->bus_cfg & DW_IC_CON_SPEED_MASK;
++      }
++
++      dev->master_cfg = (controller->bus_cfg & ~DW_IC_CON_SPEED_MASK) | mode;
+       if (controller->scl_sda_cfg) {
+               cfg = controller->scl_sda_cfg;
+               dev->ss_hcnt = cfg->ss_hcnt;
+-              dev->fs_hcnt = cfg->fs_hcnt;
+               dev->ss_lcnt = cfg->ss_lcnt;
+-              dev->fs_lcnt = cfg->fs_lcnt;
++              if (chan_opts[channel].speed == i2c_fplus) {
++                      dev->fs_hcnt = cfg->fp_hcnt;
++                      dev->fs_lcnt = cfg->fp_lcnt;
++              } else {
++                      dev->fs_hcnt = cfg->fs_hcnt;
++                      dev->fs_lcnt = cfg->fs_lcnt;
++              }
+               dev->sda_hold_time = cfg->sda_hold;
+       }
+ 
+@@ -359,6 +433,8 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_allow(&pdev->dev);
+ 
++      channel++;
++
+       return 0;
+ }
+ 
+@@ -410,7 +486,23 @@ static struct pci_driver dw_i2c_driver = {
+       },
+ };
+ 
+-module_pci_driver(dw_i2c_driver);
++static int __init
++i2c_dw_pci_init(void)
++{
++      if (flags)
++              i2c_dw_parse_flags(flags);
++
++      return pci_register_driver(&dw_i2c_driver);
++}
++
++static void __exit
++i2c_dw_pci_exit(void)
++{
++      pci_unregister_driver(&dw_i2c_driver);
++}
++
++module_init(i2c_dw_pci_init);
++module_exit(i2c_dw_pci_exit);
+ 
+ MODULE_AUTHOR("Baruch Siach <bar...@tkos.co.il>");
+ MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
+index e0f0c64..530b9d1 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -43,10 +43,61 @@
+ #include <linux/acpi.h>
+ #include "i2c-designware-core.h"
+ 
++static char *flags;
++module_param(flags, charp, 0444);
++MODULE_PARM_DESC(flags, "colon-delimited per-channel flags: [sfp]\n"
++"     s - standard speed (100KHz)\n"
++"     f - fast speed (400KHz)\n"
++"     p - fast-plus speed (1000kHz)\n");
++
++#define MAX_CHANNELS  7
++
++enum i2c_speeds {
++      i2c_none = 0,
++      i2c_ss,
++      i2c_fs,
++      i2c_fplus,
++};
++
++static struct chan_opts {
++      enum i2c_speeds speed;
++} chan_opts[MAX_CHANNELS];
++
+ static struct i2c_algorithm i2c_dw_algo = {
+       .master_xfer    = i2c_dw_xfer,
+       .functionality  = i2c_dw_func,
+ };
++
++static void i2c_dw_parse_flags(char *flags)
++{
++      char *p = flags;
++      int i;
++
++      for (i = 0; i < MAX_CHANNELS; p++) {
++              if (!*p)
++                      break;
++              switch (*p) {
++              case 's':
++                      chan_opts[i].speed = i2c_ss;
++                      break;
++              case 'f':
++                      chan_opts[i].speed = i2c_fs;
++                      break;
++              case 'p':
++                      chan_opts[i].speed = i2c_fplus;
++                      break;
++              case ':':
++                      i++; /* next channel */
++                      break;
++              default:
++                      pr_err("i2c-designware-platform: invalid "
++                             "flag %c for channel %d\n", *p, i);
++              }
++      }
++}
++
++static int channel = 0;
++
+ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+ {
+       return clk_get_rate(dev->clk)/1000;
+@@ -79,7 +130,6 @@ static void dw_i2c_acpi_params(struct platform_device 
*pdev, char method[],
+ static int dw_i2c_acpi_configure(struct platform_device *pdev)
+ {
+       struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+-      bool fs_mode = dev->master_cfg & DW_IC_CON_SPEED_FAST;
+ 
+       if (!ACPI_HANDLE(&pdev->dev))
+               return -ENODEV;
+@@ -91,9 +141,13 @@ static int dw_i2c_acpi_configure(struct platform_device 
*pdev)
+        * it exists for both supported speed modes.
+        */
+       dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt,
+-                         fs_mode ? NULL : &dev->sda_hold_time);
+-      dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
+-                         fs_mode ? &dev->sda_hold_time : NULL);
++                         NULL);
++      if (chan_opts[channel].speed == i2c_fplus)
++              dw_i2c_acpi_params(pdev, "FPCN", &dev->fs_hcnt, &dev->fs_lcnt,
++                                 &dev->sda_hold_time);
++      else
++              dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
++                                 &dev->sda_hold_time);
+ 
+       return 0;
+ }
+@@ -162,7 +216,22 @@ static int dw_i2c_probe(struct platform_device *pdev)
+               I2C_FUNC_SMBUS_WORD_DATA |
+               I2C_FUNC_SMBUS_I2C_BLOCK;
+       dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+-              DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
++              DW_IC_CON_RESTART_EN;
++
++      if (channel >= MAX_CHANNELS) {
++              dev_warn(dev->dev, "Using default params\n");
++              channel = MAX_CHANNELS - 1;
++              memset(&chan_opts[channel], 0, sizeof(struct chan_opts));
++      }
++
++      if (chan_opts[channel].speed == i2c_ss) {
++              dev->master_cfg |= DW_IC_CON_SPEED_STD;
++      } else if (chan_opts[channel].speed == i2c_fs ||
++              chan_opts[channel].speed == i2c_fplus) {
++              dev->master_cfg |= DW_IC_CON_SPEED_FAST;
++      } else {
++              dev->master_cfg |= DW_IC_CON_SPEED_FAST;
++      }
+ 
+ #ifdef CONFIG_ACPI
+       dw_i2c_acpi_configure(pdev);
+@@ -203,6 +272,7 @@ static int dw_i2c_probe(struct platform_device *pdev)
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+ 
++      channel++;
+       return 0;
+ }
+ 
+@@ -275,6 +345,8 @@ static struct platform_driver dw_i2c_driver = {
+ 
+ static int __init dw_i2c_init_driver(void)
+ {
++      if (flags)
++              i2c_dw_parse_flags(flags);
+       return platform_driver_register(&dw_i2c_driver);
+ }
+ subsys_initcall(dw_i2c_init_driver);
+-- 
+1.7.7.6
+
diff --git a/features/soc/baytrail/i2c-designware-cleanup-__i2c_dw_enable.patch 
b/features/soc/baytrail/i2c-designware-cleanup-__i2c_dw_enable.patch
new file mode 100644
index 0000000..92b2537
--- /dev/null
+++ b/features/soc/baytrail/i2c-designware-cleanup-__i2c_dw_enable.patch
@@ -0,0 +1,54 @@
+From a12e523011a2e92fe4a6c7e2be2047a1e1c64985 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:14:25 +0800
+Subject: [PATCH 124/164] i2c: designware: cleanup __i2c_dw_enable()
+
+- Do not write boolean value to register (and implicitly depend on match
+  between boolean representation and register bit position).
+
+- Do not implicitly depend on same bit position of enable bit in Enable
+  and Enable Status registers.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-core.c |    9 +++++++--
+ 1 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
+index d60d8da..896d711 100644
+--- a/drivers/i2c/busses/i2c-designware-core.c
++++ b/drivers/i2c/busses/i2c-designware-core.c
+@@ -66,12 +66,14 @@
+ #define DW_IC_CLR_START_DET   0x64
+ #define DW_IC_CLR_GEN_CALL    0x68
+ #define DW_IC_ENABLE          0x6c
++# define DW_IC_ENABLE_EN      BIT(0)
+ #define DW_IC_STATUS          0x70
+ #define DW_IC_TXFLR           0x74
+ #define DW_IC_RXFLR           0x78
+ #define DW_IC_SDA_HOLD                0x7c
+ #define DW_IC_TX_ABRT_SOURCE  0x80
+ #define DW_IC_ENABLE_STATUS   0x9c
++# define DW_IC_ENABLE_STATUS_EN       BIT(0)
+ #define DW_IC_COMP_PARAM_1    0xf4
+ #define DW_IC_COMP_VERSION    0xf8
+ #define DW_IC_SDA_HOLD_MIN_VERS       0x3131312A
+@@ -259,10 +261,13 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, 
int offset)
+ static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
+ {
+       int timeout = 100;
++      u32 status;
+ 
+       do {
+-              dw_writel(dev, enable, DW_IC_ENABLE);
+-              if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
++              dw_writel(dev, enable ? DW_IC_ENABLE_EN : 0, DW_IC_ENABLE);
++              status = dw_readl(dev, DW_IC_ENABLE_STATUS);
++              if ((enable && (status & DW_IC_ENABLE_STATUS_EN)) ||
++                  (!enable && !(status & DW_IC_ENABLE_STATUS_EN)))
+                       return;
+ 
+               /*
+-- 
+1.7.7.6
+
diff --git 
a/features/soc/baytrail/i2c-designware-cleanup-irq-handler-setting.patch 
b/features/soc/baytrail/i2c-designware-cleanup-irq-handler-setting.patch
new file mode 100644
index 0000000..da5ee02
--- /dev/null
+++ b/features/soc/baytrail/i2c-designware-cleanup-irq-handler-setting.patch
@@ -0,0 +1,53 @@
+From b4dd652adaf7192c7ef905b9f88692109311fdd0 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:13:56 +0800
+Subject: [PATCH 121/164] i2c: designware: cleanup irq handler setting
+
+Disable irq and clear any pending interrupts both in PCI and platform
+driver, do so before setting interrupt handler.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-pcidrv.c  |    5 +++--
+ drivers/i2c/busses/i2c-designware-platdrv.c |    2 ++
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index bd7b6b7..4a2a2a3 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -375,6 +375,9 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+ 
+       snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci");
+ 
++      i2c_dw_disable_int(dev);
++      i2c_dw_clear_int(dev);
++
+       r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr, IRQF_SHARED,
+                       adap->name, dev);
+       if (r) {
+@@ -382,8 +385,6 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+               return r;
+       }
+ 
+-      i2c_dw_disable_int(dev);
+-      i2c_dw_clear_int(dev);
+       r = i2c_add_numbered_adapter(adap);
+       if (r) {
+               dev_err(&pdev->dev, "failure adding adapter\n");
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
+index d0bdac0..9b9ce46 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -185,6 +185,8 @@ static int dw_i2c_probe(struct platform_device *pdev)
+               return r;
+ 
+       i2c_dw_disable_int(dev);
++      i2c_dw_clear_int(dev);
++
+       r = devm_request_irq(&pdev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
+                       pdev->name, dev);
+       if (r) {
+-- 
+1.7.7.6
+
diff --git 
a/features/soc/baytrail/i2c-designware-explicitly-abort-running-operation-on.patch
 
b/features/soc/baytrail/i2c-designware-explicitly-abort-running-operation-on.patch
new file mode 100644
index 0000000..52bb9de
--- /dev/null
+++ 
b/features/soc/baytrail/i2c-designware-explicitly-abort-running-operation-on.patch
@@ -0,0 +1,70 @@
+From 48423cfcaee8dcb7f313ca49bd11f2d7fa145f05 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:14:34 +0800
+Subject: [PATCH 125/164] i2c: designware: explicitly abort running operation
+ on disable
+
+Failure to disable causes hard device hangs in some situations
+involving timeouts.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-core.c |   19 ++++++++++++++++++-
+ 1 files changed, 18 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
+index 896d711..f867c9b 100644
+--- a/drivers/i2c/busses/i2c-designware-core.c
++++ b/drivers/i2c/busses/i2c-designware-core.c
+@@ -67,7 +67,9 @@
+ #define DW_IC_CLR_GEN_CALL    0x68
+ #define DW_IC_ENABLE          0x6c
+ # define DW_IC_ENABLE_EN      BIT(0)
++# define DW_IC_ENABLE_ABRT    BIT(1)
+ #define DW_IC_STATUS          0x70
++# define DW_IC_STATUS_MST_ACT BIT(5)
+ #define DW_IC_TXFLR           0x74
+ #define DW_IC_RXFLR           0x78
+ #define DW_IC_SDA_HOLD                0x7c
+@@ -174,6 +176,8 @@ static char *abort_sources[] = {
+               "lost arbitration",
+ };
+ 
++static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
++
+ u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+ {
+       u32 value;
+@@ -263,6 +267,17 @@ static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool 
enable)
+       int timeout = 100;
+       u32 status;
+ 
++      if (!enable &&
++          (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_MST_ACT)) {
++              /* Must abort if some activity is pending. */
++              /* Enable first before */
++              dw_writel(dev, DW_IC_ENABLE_EN, DW_IC_ENABLE);
++              /* aborting. */
++              dw_writel(dev, DW_IC_ENABLE_EN | DW_IC_ENABLE_ABRT,
++                        DW_IC_ENABLE);
++              i2c_dw_wait_bus_not_busy(dev); /* wait for abort completion */
++      }
++
+       do {
+               dw_writel(dev, enable ? DW_IC_ENABLE_EN : 0, DW_IC_ENABLE);
+               status = dw_readl(dev, DW_IC_ENABLE_STATUS);
+@@ -642,8 +657,10 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
+       dev->rx_outstanding = 0;
+ 
+       ret = i2c_dw_wait_bus_not_busy(dev);
+-      if (ret < 0)
++      if (ret < 0) {
++              i2c_dw_disable(dev);
+               goto done;
++      }
+ 
+       /* start the transfers */
+       i2c_dw_xfer_init(dev);
+-- 
+1.7.7.6
+
diff --git 
a/features/soc/baytrail/i2c-designware-improve-FIFO-performance.patch 
b/features/soc/baytrail/i2c-designware-improve-FIFO-performance.patch
new file mode 100644
index 0000000..5a546b3
--- /dev/null
+++ b/features/soc/baytrail/i2c-designware-improve-FIFO-performance.patch
@@ -0,0 +1,137 @@
+From cf20fd639b092e94c4ee55b8c7f80234df3419bf Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:14:43 +0800
+Subject: [PATCH 126/164] i2c: designware: improve FIFO performance
+
+There is no need to catch interrupt after every byte transmitted or
+received, as driver currently does. Hardware has deep FIFOs that allow
+much less software intervention.
+
+This patch reworks FIFO handling such that up to 3/4 of FIFO depth is
+processed per one interrupt. This results into significant decrease of
+number of interrupts and increase of performance.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-core.c |   34 ++++++++++++++++-------------
+ 1 files changed, 19 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
+index f867c9b..c359775 100644
+--- a/drivers/i2c/busses/i2c-designware-core.c
++++ b/drivers/i2c/busses/i2c-designware-core.c
+@@ -387,8 +387,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
+       dev->rx_fifo_depth = ((comp_param1 >> 8) & 0xff) + 1;
+       dev_dbg(dev->dev, "Tx/Rx FIFO sizes: %d/%d\n",
+                       dev->tx_fifo_depth, dev->rx_fifo_depth);
+-      dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+-      dw_writel(dev, 0, DW_IC_RX_TL);
++      dw_writel(dev, dev->tx_fifo_depth / 4, DW_IC_TX_TL);
++      dw_writel(dev, dev->rx_fifo_depth * 3 / 4, DW_IC_RX_TL);
+ 
+       /* configure the i2c master */
+       dw_writel(dev, dev->master_cfg , DW_IC_CON);
+@@ -452,9 +452,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
+       /* Enable the adapter */
+       __i2c_dw_enable(dev, true);
+ 
+-      /* Clear and enable interrupts */
++      /* Clear interrupts, they will be enabled in 'xfer' function */
+       i2c_dw_clear_int(dev);
+-      dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
+ }
+ 
+ /*
+@@ -511,7 +510,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+               }
+ 
+               tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
+-              rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
++              rx_limit = dev->rx_fifo_depth - dev->rx_outstanding;
+ 
+               while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+                       u32 cmd = 0;
+@@ -532,11 +531,6 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+                       }
+ 
+                       if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+-
+-                              /* avoid rx buffer overrun */
+-                              if (rx_limit - dev->rx_outstanding <= 0)
+-                                      break;
+-
+                               dw_writel(dev, cmd | DW_IC_CMD_READ,
+                                         DW_IC_DATA_CMD);
+                               rx_limit--;
+@@ -570,11 +564,12 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+       dw_writel(dev, intr_mask,  DW_IC_INTR_MASK);
+ }
+ 
+-static void
++static int
+ i2c_dw_read(struct dw_i2c_dev *dev)
+ {
+       struct i2c_msg *msgs = dev->msgs;
+       int rx_valid;
++      int count = 0;
+ 
+       for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
+               u32 len;
+@@ -596,16 +591,19 @@ i2c_dw_read(struct dw_i2c_dev *dev)
+               for (; len > 0 && rx_valid > 0; len--, rx_valid--) {
+                       *buf++ = dw_readl(dev, DW_IC_DATA_CMD);
+                       dev->rx_outstanding--;
++                      count++;
+               }
+ 
+               if (len > 0) {
+                       dev->status |= STATUS_READ_IN_PROGRESS;
+                       dev->rx_buf_len = len;
+                       dev->rx_buf = buf;
+-                      return;
++                      return count;
+               } else
+                       dev->status &= ~STATUS_READ_IN_PROGRESS;
+       }
++
++      return count;
+ }
+ 
+ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
+@@ -665,6 +663,8 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
+       /* start the transfers */
+       i2c_dw_xfer_init(dev);
+ 
++      /* Fill up TX buffer and enable interrupts */
++      i2c_dw_xfer_msg(dev);
+       /* wait for tx to complete */
+       ret = wait_for_completion_timeout(&dev->cmd_complete, HZ);
+       if (ret == 0) {
+@@ -781,6 +781,7 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+ {
+       struct dw_i2c_dev *dev = dev_id;
+       u32 stat, enabled;
++      int read_count = 0;
+ 
+       enabled = dw_readl(dev, DW_IC_ENABLE);
+       stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
+@@ -803,10 +804,13 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+               goto tx_aborted;
+       }
+ 
+-      if (stat & DW_IC_INTR_RX_FULL)
+-              i2c_dw_read(dev);
++      if ((stat & (DW_IC_INTR_RX_FULL | DW_IC_INTR_STOP_DET)) ||
++          dev->rx_outstanding)
++              read_count = i2c_dw_read(dev);
+ 
+-      if (stat & DW_IC_INTR_TX_EMPTY)
++      /* Allow TX_EMPTY intr if TX queue is not empty */
++      if ((read_count && dev->status & STATUS_WRITE_IN_PROGRESS) ||
++          (stat & DW_IC_INTR_TX_EMPTY))
+               i2c_dw_xfer_msg(dev);
+ 
+       /*
+-- 
+1.7.7.6
+
diff --git 
a/features/soc/baytrail/i2c-designware-use-hardware-provided-Rx-Tx-FIFO-dept.patch
 
b/features/soc/baytrail/i2c-designware-use-hardware-provided-Rx-Tx-FIFO-dept.patch
new file mode 100644
index 0000000..c6b8fcd
--- /dev/null
+++ 
b/features/soc/baytrail/i2c-designware-use-hardware-provided-Rx-Tx-FIFO-dept.patch
@@ -0,0 +1,220 @@
+From 533841a28abf7d3feca8aee92478047d386755dc Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:14:05 +0800
+Subject: [PATCH 122/164] i2c: designware: use hardware-provided Rx/Tx FIFO
+ depths
+
+i2c-designware module provides information about actual Rx/Tx FIFO
+depths in COMP_PARAM1 register.
+
+Current driver uses these hardware-provided values only in case of
+non-ACPI platform device. For all other cases (which includes all
+Bay Trail cases) hardcoded value of 32 is used instead - which leads to
+suboptimal FIFO use.
+
+This patch switches to using hardware-provided values in all cases.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-core.c    | 14 +++++++-------
+ drivers/i2c/busses/i2c-designware-core.h    |  1 -
+ drivers/i2c/busses/i2c-designware-pcidrv.c  | 24 ------------------------
+ drivers/i2c/busses/i2c-designware-platdrv.c | 18 +++---------------
+ 4 files changed, 10 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
+index d95b930..f5d4ce3 100644
+--- a/drivers/i2c/busses/i2c-designware-core.c
++++ b/drivers/i2c/busses/i2c-designware-core.c
+@@ -286,7 +286,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
+ {
+       u32 input_clock_khz;
+       u32 hcnt, lcnt;
+-      u32 reg;
++      u32 reg, comp_param1;
+ 
+       input_clock_khz = dev->get_clk_rate_khz(dev);
+ 
+@@ -303,6 +303,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
+               return -ENODEV;
+       }
+ 
++      comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
++
+       /* Disable the adapter */
+       __i2c_dw_enable(dev, false);
+ 
+@@ -358,6 +360,10 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
+       }
+ 
+       /* Configure Tx/Rx FIFO threshold levels */
++      dev->tx_fifo_depth = ((comp_param1 >> 16) & 0xff) + 1;
++      dev->rx_fifo_depth = ((comp_param1 >> 8) & 0xff) + 1;
++      dev_dbg(dev->dev, "Tx/Rx FIFO sizes: %d/%d\n",
++                      dev->tx_fifo_depth, dev->rx_fifo_depth);
+       dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+       dw_writel(dev, 0, DW_IC_RX_TL);
+ 
+@@ -827,11 +833,5 @@ void i2c_dw_disable_int(struct dw_i2c_dev *dev)
+ }
+ EXPORT_SYMBOL_GPL(i2c_dw_disable_int);
+ 
+-u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
+-{
+-      return dw_readl(dev, DW_IC_COMP_PARAM_1);
+-}
+-EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
+-
+ MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
+index e8a7565..e59dc2c 100644
+--- a/drivers/i2c/busses/i2c-designware-core.h
++++ b/drivers/i2c/busses/i2c-designware-core.h
+@@ -120,4 +120,3 @@ extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
+ extern void i2c_dw_disable(struct dw_i2c_dev *dev);
+ extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
+ extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
+-extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index 385909e..4579a5e 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -69,8 +69,6 @@ struct dw_scl_sda_cfg {
+ struct dw_pci_controller {
+       u32 bus_num;
+       u32 bus_cfg;
+-      u32 tx_fifo_depth;
+-      u32 rx_fifo_depth;
+       u32 clk_khz;
+       u32 functionality;
+       struct dw_scl_sda_cfg *scl_sda_cfg;
+@@ -99,71 +97,51 @@ static struct  dw_pci_controller  dw_pci_controllers[] = {
+       [moorestown_0] = {
+               .bus_num     = 0,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [moorestown_1] = {
+               .bus_num     = 1,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [moorestown_2] = {
+               .bus_num     = 2,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_0] = {
+               .bus_num     = 0,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_1] = {
+               .bus_num     = 1,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_2] = {
+               .bus_num     = 2,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_3] = {
+               .bus_num     = 3,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_4] = {
+               .bus_num     = 4,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_5] = {
+               .bus_num     = 5,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [baytrail] = {
+               .bus_num = -1,
+               .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+-              .tx_fifo_depth = 32,
+-              .rx_fifo_depth = 32,
+               .clk_khz = 100000,
+               .functionality = I2C_FUNC_10BIT_ADDR,
+               .scl_sda_cfg = &byt_config,
+@@ -299,8 +277,6 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+ 
+       pci_set_drvdata(pdev, dev);
+ 
+-      dev->tx_fifo_depth = controller->tx_fifo_depth;
+-      dev->rx_fifo_depth = controller->rx_fifo_depth;
+       r = i2c_dw_init(dev);
+       if (r)
+               return r;
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
+index 8aad948..3834bc2 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -105,8 +105,6 @@ static int dw_i2c_acpi_configure(struct platform_device 
*pdev)
+               return -ENODEV;
+ 
+       dev->adapter.nr = -1;
+-      dev->tx_fifo_depth = 32;
+-      dev->rx_fifo_depth = 32;
+ 
+       /*
+        * Try to get SDA hold time and *CNT values from an ACPI method if
+@@ -129,11 +127,6 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
+       { }
+ };
+ MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
+-#else
+-static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
+-{
+-      return -ENODEV;
+-}
+ #endif
+ 
+ static int dw_i2c_probe(struct platform_device *pdev)
+@@ -191,15 +184,10 @@ static int dw_i2c_probe(struct platform_device *pdev)
+       dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+               DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+ 
+-      /* Try first if we can configure the device from ACPI */
+-      r = dw_i2c_acpi_configure(pdev);
+-      if (r) {
+-              u32 param1 = i2c_dw_read_comp_param(dev);
++#ifdef CONFIG_ACPI
++      dw_i2c_acpi_configure(pdev);
++#endif
+ 
+-              dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+-              dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+-              dev->adapter.nr = pdev->id;
+-      }
+       r = i2c_dw_init(dev);
+       if (r)
+               return r;
+-- 
+1.9.1
+
+
diff --git 
a/features/soc/baytrail/i2c-designware-use-symbolic-names-for-command-bits.patch
 
b/features/soc/baytrail/i2c-designware-use-symbolic-names-for-command-bits.patch
new file mode 100644
index 0000000..7f98525
--- /dev/null
+++ 
b/features/soc/baytrail/i2c-designware-use-symbolic-names-for-command-bits.patch
@@ -0,0 +1,50 @@
+From 548a004593a14b948af1dcff00ff013137511554 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+Date: Wed, 29 Jul 2015 18:14:14 +0800
+Subject: [PATCH 123/164] i2c: designware: use symbolic names for command bits
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.moha...@intel.com>
+---
+ drivers/i2c/busses/i2c-designware-core.c |   10 +++++++---
+ 1 files changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
+index f5d4ce3..d60d8da 100644
+--- a/drivers/i2c/busses/i2c-designware-core.c
++++ b/drivers/i2c/busses/i2c-designware-core.c
+@@ -42,6 +42,9 @@
+ #define DW_IC_CON             0x0
+ #define DW_IC_TAR             0x4
+ #define DW_IC_DATA_CMD                0x10
++# define DW_IC_CMD_READ               BIT(8)
++# define DW_IC_CMD_STOP               BIT(9)
++# define DW_IC_CMD_RESTART    BIT(10)
+ #define DW_IC_SS_SCL_HCNT     0x14
+ #define DW_IC_SS_SCL_LCNT     0x18
+ #define DW_IC_FS_SCL_HCNT     0x1c
+@@ -501,10 +504,10 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+                        */
+                       if (dev->msg_write_idx == dev->msgs_num - 1 &&
+                           buf_len == 1)
+-                              cmd |= BIT(9);
++                              cmd |= DW_IC_CMD_STOP;
+ 
+                       if (need_restart) {
+-                              cmd |= BIT(10);
++                              cmd |= DW_IC_CMD_RESTART;
+                               need_restart = false;
+                       }
+ 
+@@ -514,7 +517,8 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+                               if (rx_limit - dev->rx_outstanding <= 0)
+                                       break;
+ 
+-                              dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD);
++                              dw_writel(dev, cmd | DW_IC_CMD_READ,
++                                        DW_IC_DATA_CMD);
+                               rx_limit--;
+                               dev->rx_outstanding++;
+                       } else
+-- 
+1.7.7.6
+
-- 
1.9.1

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to