All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC] Splitting i2c-designware.c to support PCI drivers
@ 2011-01-14 19:27 dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

This patch set splits i2c-designware.c core and bus specific portions
in to support the Designware core being behind a PCI device.

The Intel Moorsetown and Medfield SOC's are supported in the PCI
portion of the driver.

This patch set is still a work in progress while I work with Shinya to
make sure I did not break anything on the platform driver side.  The
runtime power management stuff needs more test but doesn't break
anything but I am not sure it's right either. This has been tested on
the Intel Moorestown development platform. 

TODO:
Move the values used for  DW_IC_[FS,SS]_SCL_HCNT
DW_IC_[FS,SS]_SCL_LCNT to be adapter/contoller specific  

Comments/Suggestions gratefully accepted.
--Dirk

Dirk Brandewie (9):
  i2c-designware: Add designware PCI config option
  i2c-designware: Initial split of i2c-designware.c into core and bus
    specific parts
  i2c-designware: retrieve clock frequency based CONFIG_HAVE_CLK
  i2c-designware: Add support for Designware core behind PCI devices.
  i2c-designware: move i2c functionality bit field to be adapter
    specific
  i2c-designware: move controller config to bus specific portion of
    driver
  i2c-designware: Allow mixed endianness accesses
  i2c-designware-pci: Add runtime power management support
  i2c-designware: Support multiple cores using same ISR

 drivers/i2c/busses/Kconfig               |   20 +
 drivers/i2c/busses/Makefile              |    4 +
 drivers/i2c/busses/i2c-designware-core.c |  619 ++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-designware-core.h |  214 ++++++++++
 drivers/i2c/busses/i2c-designware-pci.c  |  403 +++++++++++++++++++
 drivers/i2c/busses/i2c-designware-plat.c |  210 ++++++++++
 6 files changed, 1470 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-designware-core.c
 create mode 100644 drivers/i2c/busses/i2c-designware-core.h
 create mode 100644 drivers/i2c/busses/i2c-designware-pci.c
 create mode 100644 drivers/i2c/busses/i2c-designware-plat.c

-- 
1.7.3.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/9] i2c-designware: Add designware PCI config option
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  2011-01-14 19:27   ` [PATCH 2/9] i2c-designware: Initial split of i2c-designware.c into core and bus specific parts dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/Kconfig |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index f1a6eeb..5847611 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -346,6 +346,26 @@ config I2C_DAVINCI
 	  devices such as DaVinci NIC.
 	  For details please see http://www.ti.com/davinci
 
+
+config I2C_DESIGNWARE_PCI
+	tristate "Synopsys DesignWare PCI"
+	help
+	  If you say yes to this option, support will be included for the
+	  Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-designware.
+
+config I2C_DESIGNWARE_PLATFORM
+	tristate "Synopsys DesignWare Platform"
+	depends on HAVE_CLK
+	help
+	  If you say yes to this option, support will be included for the
+	  Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-designware.
+
 config I2C_DESIGNWARE
 	tristate "Synopsys DesignWare"
 	depends on HAVE_CLK
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/9] i2c-designware: Initial split of i2c-designware.c into core and bus specific parts
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-14 19:27   ` [PATCH 1/9] i2c-designware: Add designware PCI config option dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
       [not found]     ` <1295033256-30077-3-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-14 19:27   ` [PATCH 3/9] i2c-designware: retrieve clock frequency based CONFIG_HAVE_CLK dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

This patch splits i2c-designware.c into a core library and associated
header file and two bus specific parts for platform bus and PCI bus.

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/Makefile              |    4 +
 drivers/i2c/busses/i2c-designware-core.c |  541 ++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-designware-core.h |  204 +++++++++++
 drivers/i2c/busses/i2c-designware-pci.c  |  183 ++++++++++
 drivers/i2c/busses/i2c-designware-plat.c |  198 +++++++++++
 5 files changed, 1130 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-designware-core.c
 create mode 100644 drivers/i2c/busses/i2c-designware-core.h
 create mode 100644 drivers/i2c/busses/i2c-designware-pci.c
 create mode 100644 drivers/i2c/busses/i2c-designware-plat.c

diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 0b9aa00..e1c0774 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -34,6 +34,10 @@ obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
 obj-$(CONFIG_I2C_DESIGNWARE)	+= i2c-designware.o
+obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c_dw_pci.o
+i2c_dw_pci-objs := i2c-designware-pci.o i2c-designware-core.o
+obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c_dw_plat.o
+i2c_dw_plat-objs := i2c-designware-plat.o i2c-designware-core.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
new file mode 100644
index 0000000..9dca409
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -0,0 +1,541 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "i2c-designware-core.h"
+
+static char *abort_sources[] = {
+	[ABRT_7B_ADDR_NOACK] =
+		"slave address not acknowledged (7bit mode)",
+	[ABRT_10ADDR1_NOACK] =
+		"first address byte not acknowledged (10bit mode)",
+	[ABRT_10ADDR2_NOACK] =
+		"second address byte not acknowledged (10bit mode)",
+	[ABRT_TXDATA_NOACK] =
+		"data not acknowledged",
+	[ABRT_GCALL_NOACK] =
+		"no acknowledgement for a general call",
+	[ABRT_GCALL_READ] =
+		"read after general call",
+	[ABRT_SBYTE_ACKDET] =
+		"start byte acknowledged",
+	[ABRT_SBYTE_NORSTRT] =
+		"trying to send start byte when restart is disabled",
+	[ABRT_10B_RD_NORSTRT] =
+		"trying to read when restart is disabled (10bit mode)",
+	[ABRT_MASTER_DIS] =
+		"trying to use disabled adapter",
+	[ARB_LOST] =
+		"lost arbitration",
+};
+
+u32
+i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
+{
+	/*
+	 * DesignWare I2C core doesn't seem to have solid strategy to meet
+	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
+	 * will result in violation of the tHD;STA spec.
+	 */
+	if (cond)
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
+		 *
+		 * This is based on the DW manuals, and represents an ideal
+		 * configuration.  The resulting I2C bus speed will be
+		 * faster than any of the others.
+		 *
+		 * If your hardware is free from tHD;STA issue, try this one.
+		 */
+		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
+	else
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
+		 *
+		 * This is just experimental rule; the tHD;STA period turned
+		 * out to be proportinal to (_HCNT + 3).  With this setting,
+		 * we could meet both tHIGH and tHD;STA timing specs.
+		 *
+		 * If unsure, you'd better to take this alternative.
+		 *
+		 * The reason why we need to take into account "tf" here,
+		 * is the same as described in i2c_dw_scl_lcnt().
+		 */
+		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
+}
+
+u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
+{
+	/*
+	 * Conditional expression:
+	 *
+	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
+	 *
+	 * DW I2C core starts counting the SCL CNTs for the LOW period
+	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
+	 * In order to meet the tLOW timing spec, we need to take into
+	 * account the fall time of SCL signal (tf).  Default tf value
+	 * should be 0.3 us, for safety.
+	 */
+	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
+}
+
+/**
+ * i2c_dw_init() - initialize the designware i2c master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+void
+i2c_dw_init(struct dw_i2c_dev *dev)
+{
+	u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
+	u32 ic_con, hcnt, lcnt;
+
+	/* Disable the adapter */
+	writel(0, dev->base + DW_IC_ENABLE);
+
+	/* set standard and fast speed deviders for high/low periods */
+
+	/* Standard-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				40,	/* tHD;STA = tHIGH = 4.0 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				47,	/* tLOW = 4.7 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	writel(hcnt, dev->base + DW_IC_SS_SCL_HCNT);
+	writel(lcnt, dev->base + DW_IC_SS_SCL_LCNT);
+	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Fast-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				6,	/* tHD;STA = tHIGH = 0.6 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				13,	/* tLOW = 1.3 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	writel(hcnt, dev->base + DW_IC_FS_SCL_HCNT);
+	writel(lcnt, dev->base + DW_IC_FS_SCL_LCNT);
+	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Configure Tx/Rx FIFO threshold levels */
+	writel(dev->tx_fifo_depth - 1, dev->base + DW_IC_TX_TL);
+	writel(0, dev->base + DW_IC_RX_TL);
+
+	/* configure the i2c master */
+	ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+	writel(ic_con, dev->base + DW_IC_CON);
+}
+EXPORT_SYMBOL(i2c_dw_init);
+
+/*
+ * Waiting for bus not busy
+ */
+int
+i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
+{
+	int timeout = TIMEOUT;
+
+	while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+		if (timeout <= 0) {
+			dev_warn(dev->dev, "timeout waiting for bus ready\n");
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+void
+i2c_dw_xfer_init(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 ic_con;
+
+	/* Disable the adapter */
+	writel(0, dev->base + DW_IC_ENABLE);
+
+	/* set the slave (target) address */
+	writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
+
+	/* if the slave address is ten bit address, enable 10BITADDR */
+	ic_con = readl(dev->base + DW_IC_CON);
+	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+		ic_con |= DW_IC_CON_10BITADDR_MASTER;
+	else
+		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+	writel(ic_con, dev->base + DW_IC_CON);
+
+	/* Enable the adapter */
+	writel(1, dev->base + DW_IC_ENABLE);
+
+	/* Enable interrupts */
+	writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
+}
+
+/*
+ * Initiate (and continue) low level master read/write transaction.
+ * This function is only called from i2c_dw_isr, and pumping i2c_msg
+ * messages into the tx buffer.  Even if the size of i2c_msg data is
+ * longer than the size of the tx buffer, it handles everything.
+ */
+void
+i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 intr_mask;
+	int tx_limit, rx_limit;
+	u32 addr = msgs[dev->msg_write_idx].addr;
+	u32 buf_len = dev->tx_buf_len;
+	u8 *buf = dev->tx_buf;;
+
+	intr_mask = DW_IC_INTR_DEFAULT_MASK;
+
+	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
+		/*
+		 * if target address has changed, we need to
+		 * reprogram the target address in the i2c
+		 * adapter when we are done with this transfer
+		 */
+		if (msgs[dev->msg_write_idx].addr != addr) {
+			dev_err(dev->dev,
+				"%s: invalid target address\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (msgs[dev->msg_write_idx].len == 0) {
+			dev_err(dev->dev,
+				"%s: invalid message length\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
+			/* new i2c_msg */
+			buf = msgs[dev->msg_write_idx].buf;
+			buf_len = msgs[dev->msg_write_idx].len;
+		}
+
+		tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR);
+		rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR);
+
+		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+				writel(0x100, dev->base + DW_IC_DATA_CMD);
+				rx_limit--;
+			} else
+				writel(*buf++, dev->base + DW_IC_DATA_CMD);
+			tx_limit--; buf_len--;
+		}
+
+		dev->tx_buf = buf;
+		dev->tx_buf_len = buf_len;
+
+		if (buf_len > 0) {
+			/* more bytes to be written */
+			dev->status |= STATUS_WRITE_IN_PROGRESS;
+			break;
+		} else
+			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
+	}
+
+	/*
+	 * If i2c_msg index search is completed, we don't need TX_EMPTY
+	 * interrupt any more.
+	 */
+	if (dev->msg_write_idx == dev->msgs_num)
+		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
+
+	if (dev->msg_err)
+		intr_mask = 0;
+
+	writel(intr_mask, dev->base + DW_IC_INTR_MASK);
+}
+
+void
+i2c_dw_read(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	int rx_valid;
+
+	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
+		u32 len;
+		u8 *buf;
+
+		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
+			continue;
+
+		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
+			len = msgs[dev->msg_read_idx].len;
+			buf = msgs[dev->msg_read_idx].buf;
+		} else {
+			len = dev->rx_buf_len;
+			buf = dev->rx_buf;
+		}
+
+		rx_valid = readl(dev->base + DW_IC_RXFLR);
+
+		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+			*buf++ = readl(dev->base + DW_IC_DATA_CMD);
+
+		if (len > 0) {
+			dev->status |= STATUS_READ_IN_PROGRESS;
+			dev->rx_buf_len = len;
+			dev->rx_buf = buf;
+			return;
+		} else
+			dev->status &= ~STATUS_READ_IN_PROGRESS;
+	}
+}
+
+int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
+{
+	unsigned long abort_source = dev->abort_source;
+	int i;
+
+	if (abort_source & DW_IC_TX_ABRT_NOACK) {
+		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+			dev_dbg(dev->dev,
+				"%s: %s\n", __func__, abort_sources[i]);
+		return -EREMOTEIO;
+	}
+
+	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
+
+	if (abort_source & DW_IC_TX_ARB_LOST)
+		return -EAGAIN;
+	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
+		return -EINVAL; /* wrong msgs[] data */
+	else
+		return -EIO;
+}
+
+/*
+ * Prepare controller for a transaction and call i2c_dw_xfer_msg
+ */
+int
+i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	int ret;
+
+	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
+
+	mutex_lock(&dev->lock);
+
+	INIT_COMPLETION(dev->cmd_complete);
+	dev->msgs = msgs;
+	dev->msgs_num = num;
+	dev->cmd_err = 0;
+	dev->msg_write_idx = 0;
+	dev->msg_read_idx = 0;
+	dev->msg_err = 0;
+	dev->status = STATUS_IDLE;
+	dev->abort_source = 0;
+
+	ret = i2c_dw_wait_bus_not_busy(dev);
+	if (ret < 0)
+		goto done;
+
+	/* start the transfers */
+	i2c_dw_xfer_init(dev);
+
+	/* wait for tx to complete */
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
+	if (ret == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+		i2c_dw_init(dev);
+		ret = -ETIMEDOUT;
+		goto done;
+	} else if (ret < 0)
+		goto done;
+
+	if (dev->msg_err) {
+		ret = dev->msg_err;
+		goto done;
+	}
+
+	/* no error */
+	if (likely(!dev->cmd_err)) {
+		/* Disable the adapter */
+		writel(0, dev->base + DW_IC_ENABLE);
+		ret = num;
+		goto done;
+	}
+
+	/* We have an error */
+	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
+		ret = i2c_dw_handle_tx_abort(dev);
+		goto done;
+	}
+	ret = -EIO;
+
+done:
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(i2c_dw_xfer);
+
+u32 i2c_dw_func(struct i2c_adapter *adap)
+{
+	return	I2C_FUNC_I2C |
+		I2C_FUNC_10BIT_ADDR |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+EXPORT_SYMBOL(i2c_dw_func);
+
+u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
+{
+	u32 stat;
+
+	/*
+	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
+	 * Ths unmasked raw version of interrupt status bits are available
+	 * in the IC_RAW_INTR_STAT register.
+	 *
+	 * That is,
+	 *   stat = readl(IC_INTR_STAT);
+	 * equals to,
+	 *   stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
+	 *
+	 * The raw version might be useful for debugging purposes.
+	 */
+	stat = readl(dev->base + DW_IC_INTR_STAT);
+
+	/*
+	 * Do not use the IC_CLR_INTR register to clear interrupts, or
+	 * you'll miss some interrupts, triggered during the period from
+	 * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
+	 *
+	 * Instead, use the separately-prepared IC_CLR_* registers.
+	 */
+	if (stat & DW_IC_INTR_RX_UNDER)
+		readl(dev->base + DW_IC_CLR_RX_UNDER);
+	if (stat & DW_IC_INTR_RX_OVER)
+		readl(dev->base + DW_IC_CLR_RX_OVER);
+	if (stat & DW_IC_INTR_TX_OVER)
+		readl(dev->base + DW_IC_CLR_TX_OVER);
+	if (stat & DW_IC_INTR_RD_REQ)
+		readl(dev->base + DW_IC_CLR_RD_REQ);
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		/*
+		 * The IC_TX_ABRT_SOURCE register is cleared whenever
+		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
+		 */
+		dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
+		readl(dev->base + DW_IC_CLR_TX_ABRT);
+	}
+	if (stat & DW_IC_INTR_RX_DONE)
+		readl(dev->base + DW_IC_CLR_RX_DONE);
+	if (stat & DW_IC_INTR_ACTIVITY)
+		readl(dev->base + DW_IC_CLR_ACTIVITY);
+	if (stat & DW_IC_INTR_STOP_DET)
+		readl(dev->base + DW_IC_CLR_STOP_DET);
+	if (stat & DW_IC_INTR_START_DET)
+		readl(dev->base + DW_IC_CLR_START_DET);
+	if (stat & DW_IC_INTR_GEN_CALL)
+		readl(dev->base + DW_IC_CLR_GEN_CALL);
+
+	return stat;
+}
+
+/*
+ * Interrupt service routine. This gets called whenever an I2C interrupt
+ * occurs.
+ */
+irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+{
+	struct dw_i2c_dev *dev = dev_id;
+	u32 stat;
+
+	stat = i2c_dw_read_clear_intrbits(dev);
+	dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
+
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
+		dev->status = STATUS_IDLE;
+
+		/*
+		 * Anytime TX_ABRT is set, the contents of the tx/rx
+		 * buffers are flushed.  Make sure to skip them.
+		 */
+		writel(0, dev->base + DW_IC_INTR_MASK);
+		goto tx_aborted;
+	}
+
+	if (stat & DW_IC_INTR_RX_FULL)
+		i2c_dw_read(dev);
+
+	if (stat & DW_IC_INTR_TX_EMPTY)
+		i2c_dw_xfer_msg(dev);
+
+	/*
+	 * No need to modify or disable the interrupt mask here.
+	 * i2c_dw_xfer_msg() will take care of it according to
+	 * the current transmit status.
+	 */
+
+tx_aborted:
+	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
+		complete(&dev->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(i2c_dw_isr);
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
new file mode 100644
index 0000000..9558ef2
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -0,0 +1,204 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+/*
+ * Registers offset
+ */
+#define DW_IC_CON		0x0
+#define DW_IC_TAR		0x4
+#define DW_IC_DATA_CMD		0x10
+#define DW_IC_SS_SCL_HCNT	0x14
+#define DW_IC_SS_SCL_LCNT	0x18
+#define DW_IC_FS_SCL_HCNT	0x1c
+#define DW_IC_FS_SCL_LCNT	0x20
+#define DW_IC_INTR_STAT		0x2c
+#define DW_IC_INTR_MASK		0x30
+#define DW_IC_RAW_INTR_STAT	0x34
+#define DW_IC_RX_TL		0x38
+#define DW_IC_TX_TL		0x3c
+#define DW_IC_CLR_INTR		0x40
+#define DW_IC_CLR_RX_UNDER	0x44
+#define DW_IC_CLR_RX_OVER	0x48
+#define DW_IC_CLR_TX_OVER	0x4c
+#define DW_IC_CLR_RD_REQ	0x50
+#define DW_IC_CLR_TX_ABRT	0x54
+#define DW_IC_CLR_RX_DONE	0x58
+#define DW_IC_CLR_ACTIVITY	0x5c
+#define DW_IC_CLR_STOP_DET	0x60
+#define DW_IC_CLR_START_DET	0x64
+#define DW_IC_CLR_GEN_CALL	0x68
+#define DW_IC_ENABLE		0x6c
+#define DW_IC_STATUS		0x70
+#define DW_IC_TXFLR		0x74
+#define DW_IC_RXFLR		0x78
+#define DW_IC_COMP_PARAM_1	0xf4
+#define DW_IC_TX_ABRT_SOURCE	0x80
+
+#define DW_IC_CON_MASTER		0x1
+#define DW_IC_CON_SPEED_STD		0x2
+#define DW_IC_CON_SPEED_FAST		0x4
+#define DW_IC_CON_10BITADDR_MASTER	0x10
+#define DW_IC_CON_RESTART_EN		0x20
+#define DW_IC_CON_SLAVE_DISABLE		0x40
+
+#define DW_IC_INTR_RX_UNDER	0x001
+#define DW_IC_INTR_RX_OVER	0x002
+#define DW_IC_INTR_RX_FULL	0x004
+#define DW_IC_INTR_TX_OVER	0x008
+#define DW_IC_INTR_TX_EMPTY	0x010
+#define DW_IC_INTR_RD_REQ	0x020
+#define DW_IC_INTR_TX_ABRT	0x040
+#define DW_IC_INTR_RX_DONE	0x080
+#define DW_IC_INTR_ACTIVITY	0x100
+#define DW_IC_INTR_STOP_DET	0x200
+#define DW_IC_INTR_START_DET	0x400
+#define DW_IC_INTR_GEN_CALL	0x800
+
+#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
+					 DW_IC_INTR_TX_EMPTY | \
+					 DW_IC_INTR_TX_ABRT | \
+					 DW_IC_INTR_STOP_DET)
+
+#define DW_IC_STATUS_ACTIVITY	0x1
+
+#define DW_IC_ERR_TX_ABRT	0x1
+
+/*
+ * status codes
+ */
+#define STATUS_IDLE			0x0
+#define STATUS_WRITE_IN_PROGRESS	0x1
+#define STATUS_READ_IN_PROGRESS		0x2
+
+#define TIMEOUT			20 /* ms */
+
+/*
+ * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
+ *
+ * only expected abort codes are listed here
+ * refer to the datasheet for the full list
+ */
+#define ABRT_7B_ADDR_NOACK	0
+#define ABRT_10ADDR1_NOACK	1
+#define ABRT_10ADDR2_NOACK	2
+#define ABRT_TXDATA_NOACK	3
+#define ABRT_GCALL_NOACK	4
+#define ABRT_GCALL_READ		5
+#define ABRT_SBYTE_ACKDET	7
+#define ABRT_SBYTE_NORSTRT	9
+#define ABRT_10B_RD_NORSTRT	10
+#define ABRT_MASTER_DIS		11
+#define ARB_LOST		12
+
+#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
+#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
+#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
+#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
+#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
+#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
+#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
+#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
+#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
+#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
+#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
+
+#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
+					 DW_IC_TX_ABRT_TXDATA_NOACK | \
+					 DW_IC_TX_ABRT_GCALL_NOACK)
+
+
+/**
+ * struct dw_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transfered
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ *	array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ *	array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct dw_i2c_dev {
+	struct device		*dev;
+	void __iomem		*base;
+	struct completion	cmd_complete;
+	struct mutex		lock;
+	struct clk		*clk;
+	int			cmd_err;
+	struct i2c_msg		*msgs;
+	int			msgs_num;
+	int			msg_write_idx;
+	u32			tx_buf_len;
+	u8			*tx_buf;
+	int			msg_read_idx;
+	u32			rx_buf_len;
+	u8			*rx_buf;
+	int			msg_err;
+	unsigned int		status;
+	u32			abort_source;
+	int			irq;
+	struct i2c_adapter	adapter;
+	unsigned int		tx_fifo_depth;
+	unsigned int		rx_fifo_depth;
+};
+
+
+extern void i2c_dw_init(struct dw_i2c_dev *dev);
+extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+		int num);
+extern u32 i2c_dw_func(struct i2c_adapter *adap);
+extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
new file mode 100644
index 0000000..11185b2
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-pci.c
@@ -0,0 +1,183 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "i2c-designware-core.h"
+
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	struct resource *mem, *ioarea;
+	int irq, r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return irq; /* -ENXIO */
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->dev = get_device(&pdev->dev);
+	dev->irq = irq;
+	platform_set_drvdata(pdev, dev);
+
+
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (dev->base == NULL) {
+		dev_err(&pdev->dev, "failure mapping io resources\n");
+		r = -EBUSY;
+		goto err_unuse_clocks;
+	}
+	{
+		u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
+
+		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+	}
+	i2c_dw_init(dev);
+
+	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
+	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+			sizeof(adap->name));
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+
+	adap->nr = pdev->id;
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+err_free_mem:
+	platform_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	platform_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	writel(0, dev->base + DW_IC_ENABLE);
+	free_irq(dev->irq, dev);
+	kfree(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+	.remove		= __devexit_p(dw_i2c_remove),
+	.driver		= {
+		.name	= "i2c_designware",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-plat.c b/drivers/i2c/busses/i2c-designware-plat.c
new file mode 100644
index 0000000..b8e5aa4
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-plat.c
@@ -0,0 +1,198 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "i2c-designware-core.h"
+
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	struct resource *mem, *ioarea;
+	int irq, r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return irq; /* -ENXIO */
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->dev = get_device(&pdev->dev);
+	dev->irq = irq;
+	platform_set_drvdata(pdev, dev);
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
+		r = -ENODEV;
+		goto err_free_mem;
+	}
+	clk_enable(dev->clk);
+
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (dev->base == NULL) {
+		dev_err(&pdev->dev, "failure mapping io resources\n");
+		r = -EBUSY;
+		goto err_unuse_clocks;
+	}
+	{
+		u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
+
+		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+	}
+	i2c_dw_init(dev);
+
+	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
+	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+			sizeof(adap->name));
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+
+	adap->nr = pdev->id;
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+err_unuse_clocks:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+err_free_mem:
+	platform_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	platform_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+
+	writel(0, dev->base + DW_IC_ENABLE);
+	free_irq(dev->irq, dev);
+	kfree(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+	.remove		= __devexit_p(dw_i2c_remove),
+	.driver		= {
+		.name	= "i2c_designware",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/9] i2c-designware: retrieve clock frequency based CONFIG_HAVE_CLK
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-14 19:27   ` [PATCH 1/9] i2c-designware: Add designware PCI config option dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  2011-01-14 19:27   ` [PATCH 2/9] i2c-designware: Initial split of i2c-designware.c into core and bus specific parts dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  2011-01-14 19:27   ` [PATCH 4/9] i2c-designware: Add support for Designware core behind PCI devices dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

x86 does not have clk_dev support.  The PCI variant of the driver sets
the clock rate being supplied to the IP block based on config
information attached to the PCI ID


Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/i2c-designware-core.c |   14 +++++++++++++-
 drivers/i2c/busses/i2c-designware-core.h |    1 +
 2 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 9dca409..b7102df 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -39,6 +39,16 @@
 #include <linux/slab.h>
 #include "i2c-designware-core.h"
 
+static u32 i2c_dw_clk_get_rate(struct dw_i2c_dev *dev)
+{
+#ifndef CONFIG_HAVE_CLK
+	return dev->clk_khz;
+#else
+	return clk_get_rate(dev->clk)/1000;
+#endif
+}
+
+
 static char *abort_sources[] = {
 	[ABRT_7B_ADDR_NOACK] =
 		"slave address not acknowledged (7bit mode)",
@@ -130,9 +140,11 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
 void
 i2c_dw_init(struct dw_i2c_dev *dev)
 {
-	u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
+	u32 input_clock_khz;
 	u32 ic_con, hcnt, lcnt;
 
+	input_clock_khz = i2c_dw_clk_get_rate(dev);
+
 	/* Disable the adapter */
 	writel(0, dev->base + DW_IC_ENABLE);
 
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 9558ef2..f2182a9 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -178,6 +178,7 @@ struct dw_i2c_dev {
 	struct completion	cmd_complete;
 	struct mutex		lock;
 	struct clk		*clk;
+	u32			clk_khz;
 	int			cmd_err;
 	struct i2c_msg		*msgs;
 	int			msgs_num;
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/9] i2c-designware: Add support for Designware core behind PCI devices.
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (2 preceding siblings ...)
  2011-01-14 19:27   ` [PATCH 3/9] i2c-designware: retrieve clock frequency based CONFIG_HAVE_CLK dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  2011-01-14 19:27   ` [PATCH 5/9] i2c-designware: move i2c functionality bit field to be adapter specific dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Modify the driver to be a PCI driver from the platform template
created in the inital split of the driver.  Add controller config
options attached to PCI ID's. Add for the Moorsetown
and Medfield SOC's

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/i2c-designware-pci.c |  244 +++++++++++++++++++++++--------
 1 files changed, 182 insertions(+), 62 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
index 11185b2..00717df 100644
--- a/drivers/i2c/busses/i2c-designware-pci.c
+++ b/drivers/i2c/busses/i2c-designware-pci.c
@@ -37,40 +37,156 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
 #include "i2c-designware-core.h"
 
+#define DRIVER_NAME "i2c-designware-pci"
+#define STANDARD		0
+#define FAST			1
+#define HIGH			2
+
+enum dw_pci_ctl_id_t {
+	moorestown_0,
+	moorestown_1,
+	moorestown_2,
+
+	medfield_0,
+	medfield_1,
+	medfield_2,
+	medfield_3,
+	medfield_4,
+	medfield_5,
+};
+
+struct dw_pci_controller {
+	u32 bus_num;
+	u32 bus_speed;
+	u32 tx_fifo_depth;
+	u32 rx_fifo_depth;
+	u32 clk_khz;
+};
+
+static struct  dw_pci_controller  dw_pci_controllers[] = {
+	[moorestown_0] = {
+		.bus_num     = 0,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[moorestown_1] = {
+		.bus_num     = 1,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[moorestown_2] = {
+		.bus_num     = 2,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[medfield_0] = {
+		.bus_num     = 0,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[medfield_1] = {
+		.bus_num     = 1,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[medfield_2] = {
+		.bus_num     = 2,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[medfield_3] = {
+		.bus_num     = 3,
+		.bus_speed   = STANDARD,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[medfield_4] = {
+		.bus_num     = 4,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+	[medfield_5] = {
+		.bus_num     = 5,
+		.bus_speed   = FAST,
+		.tx_fifo_depth = 64,
+		.rx_fifo_depth = 64,
+		.clk_khz      = 2500,
+	},
+};
 static struct i2c_algorithm i2c_dw_algo = {
 	.master_xfer	= i2c_dw_xfer,
 	.functionality	= i2c_dw_func,
 };
 
-static int __devinit dw_i2c_probe(struct platform_device *pdev)
+static int __devinit dw_i2c_pci_probe(struct pci_dev *pdev,
+const struct pci_device_id *id)
 {
 	struct dw_i2c_dev *dev;
 	struct i2c_adapter *adap;
-	struct resource *mem, *ioarea;
-	int irq, r;
+	unsigned long start, len;
+	void __iomem *base;
+	int r;
+	struct  dw_pci_controller *controller;
 
-	/* NOTE: driver uses the static register mapping */
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "no mem resource?\n");
+	if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+		printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n",
+			id->driver_data);
 		return -EINVAL;
 	}
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no irq resource?\n");
-		return irq; /* -ENXIO */
+	controller = &dw_pci_controllers[id->driver_data];
+
+	r = pci_enable_device(pdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
+			r);
+		goto exit;
+	}
+
+	/* Determine the address of the I2C area */
+	start = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	if (!start || len == 0) {
+		dev_err(&pdev->dev, "base address not set\n");
+		r = -ENODEV;
+		goto exit;
+	}
+
+	r = pci_request_region(pdev, 0, DRIVER_NAME);
+	if (r) {
+		dev_err(&pdev->dev, "failed to request I2C region "
+			"0x%lx-0x%lx\n", start,
+			(unsigned long)pci_resource_end(pdev, 0));
+		goto exit;
 	}
 
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-			pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "I2C region already claimed\n");
-		return -EBUSY;
+	base = ioremap_nocache(start, len);
+	if (!base) {
+		dev_err(&pdev->dev, "I/O memory remapping failed\n");
+		r = -ENOMEM;
+		goto err_release_region;
 	}
 
+
 	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
 	if (!dev) {
 		r = -ENOMEM;
@@ -79,31 +195,17 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
 
 	init_completion(&dev->cmd_complete);
 	mutex_init(&dev->lock);
+	dev->clk = NULL;
+	dev->clk_khz = controller->clk_khz;
+	dev->base = base;
 	dev->dev = get_device(&pdev->dev);
-	dev->irq = irq;
-	platform_set_drvdata(pdev, dev);
-
+	pci_set_drvdata(pdev, dev);
 
-	dev->base = ioremap(mem->start, resource_size(mem));
-	if (dev->base == NULL) {
-		dev_err(&pdev->dev, "failure mapping io resources\n");
-		r = -EBUSY;
-		goto err_unuse_clocks;
-	}
-	{
-		u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
+	dev->tx_fifo_depth = controller->tx_fifo_depth;
+	dev->rx_fifo_depth = controller->rx_fifo_depth;
 
-		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
-		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
-	}
 	i2c_dw_init(dev);
 
-	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
-	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
-	if (r) {
-		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
-		goto err_iounmap;
-	}
 
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
@@ -114,7 +216,15 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
 	adap->algo = &i2c_dw_algo;
 	adap->dev.parent = &pdev->dev;
 
-	adap->nr = pdev->id;
+	adap->nr = controller->bus_num;
+
+	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
+	r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
 	r = i2c_add_numbered_adapter(adap);
 	if (r) {
 		dev_err(&pdev->dev, "failure adding adapter\n");
@@ -124,60 +234,70 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
 	return 0;
 
 err_free_irq:
-	free_irq(dev->irq, dev);
+	free_irq(pdev->irq, dev);
 err_iounmap:
 	iounmap(dev->base);
-err_free_mem:
-	platform_set_drvdata(pdev, NULL);
+	pci_set_drvdata(pdev, NULL);
 	put_device(&pdev->dev);
 	kfree(dev);
 err_release_region:
-	release_mem_region(mem->start, resource_size(mem));
-
+	pci_release_region(pdev, 0);
+exit:
 	return r;
 }
 
-static int __devexit dw_i2c_remove(struct platform_device *pdev)
+static void __devexit dw_i2c_pci_remove(struct pci_dev *pdev)
 {
-	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
-	struct resource *mem;
+	struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
+	writel(0, dev->base + DW_IC_ENABLE);
+	pci_set_drvdata(pdev, NULL);
 	i2c_del_adapter(&dev->adapter);
 	put_device(&pdev->dev);
 
-	writel(0, dev->base + DW_IC_ENABLE);
 	free_irq(dev->irq, dev);
 	kfree(dev);
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
-	return 0;
+	pci_release_region(pdev, 0);
 }
 
 /* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c_designware");
+MODULE_ALIAS("i2c_designware-pci");
 
-static struct platform_driver dw_i2c_driver = {
-	.remove		= __devexit_p(dw_i2c_remove),
-	.driver		= {
-		.name	= "i2c_designware",
-		.owner	= THIS_MODULE,
-	},
+static struct pci_device_id i2_designware_pci_ids[] = {
+	/* Moorestown */
+	{ PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
+	{ PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
+	{ PCI_VDEVICE(INTEL, 0x0804), moorestown_2 },
+	/* Medfield */
+	{ PCI_VDEVICE(INTEL, 0x0817), medfield_3,},
+	{ PCI_VDEVICE(INTEL, 0x0818), medfield_4 },
+	{ PCI_VDEVICE(INTEL, 0x0819), medfield_5 },
+	{ PCI_VDEVICE(INTEL, 0x082C), medfield_0 },
+	{ PCI_VDEVICE(INTEL, 0x082D), medfield_1 },
+	{ PCI_VDEVICE(INTEL, 0x082E), medfield_2 },
+	{ 0,}
+};
+MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
+
+static struct pci_driver dw_i2c_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= i2_designware_pci_ids,
+	.probe		= dw_i2c_pci_probe,
+	.remove		= __devexit_p(dw_i2c_pci_remove),
 };
 
 static int __init dw_i2c_init_driver(void)
 {
-	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+	return  pci_register_driver(&dw_i2c_driver);
 }
 module_init(dw_i2c_init_driver);
 
 static void __exit dw_i2c_exit_driver(void)
 {
-	platform_driver_unregister(&dw_i2c_driver);
+	pci_unregister_driver(&dw_i2c_driver);
 }
 module_exit(dw_i2c_exit_driver);
 
-MODULE_AUTHOR("Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>");
-MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_AUTHOR("Dirk Brandewie <dirk.j.brandewie-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org");
+MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
 MODULE_LICENSE("GPL");
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/9] i2c-designware: move i2c functionality bit field to be adapter specific
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (3 preceding siblings ...)
  2011-01-14 19:27   ` [PATCH 4/9] i2c-designware: Add support for Designware core behind PCI devices dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
       [not found]     ` <1295033256-30077-6-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-14 19:27   ` [PATCH 6/9] i2c-designware: move controller config to bus specific portion of driver dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
                     ` (4 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

The functionality of the adapter depends on the configuration of the
IP block at silicon compile time and is adapter specific.

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/i2c-designware-core.c |    8 ++------
 drivers/i2c/busses/i2c-designware-core.h |    1 +
 drivers/i2c/busses/i2c-designware-pci.c  |    6 ++++++
 drivers/i2c/busses/i2c-designware-plat.c |    7 +++++++
 4 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index b7102df..c6a2b50 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -444,12 +444,8 @@ EXPORT_SYMBOL(i2c_dw_xfer);
 
 u32 i2c_dw_func(struct i2c_adapter *adap)
 {
-	return	I2C_FUNC_I2C |
-		I2C_FUNC_10BIT_ADDR |
-		I2C_FUNC_SMBUS_BYTE |
-		I2C_FUNC_SMBUS_BYTE_DATA |
-		I2C_FUNC_SMBUS_WORD_DATA |
-		I2C_FUNC_SMBUS_I2C_BLOCK;
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	return dev->functionality;
 }
 EXPORT_SYMBOL(i2c_dw_func);
 
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index f2182a9..e39a412 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -193,6 +193,7 @@ struct dw_i2c_dev {
 	u32			abort_source;
 	int			irq;
 	struct i2c_adapter	adapter;
+	u32			functionality;
 	unsigned int		tx_fifo_depth;
 	unsigned int		rx_fifo_depth;
 };
diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
index 00717df..5d131ce 100644
--- a/drivers/i2c/busses/i2c-designware-pci.c
+++ b/drivers/i2c/busses/i2c-designware-pci.c
@@ -199,6 +199,12 @@ const struct pci_device_id *id)
 	dev->clk_khz = controller->clk_khz;
 	dev->base = base;
 	dev->dev = get_device(&pdev->dev);
+	dev->functionality = I2C_FUNC_I2C |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+
 	pci_set_drvdata(pdev, dev);
 
 	dev->tx_fifo_depth = controller->tx_fifo_depth;
diff --git a/drivers/i2c/busses/i2c-designware-plat.c b/drivers/i2c/busses/i2c-designware-plat.c
index b8e5aa4..cf157a4 100644
--- a/drivers/i2c/busses/i2c-designware-plat.c
+++ b/drivers/i2c/busses/i2c-designware-plat.c
@@ -91,6 +91,13 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
 	}
 	clk_enable(dev->clk);
 
+	dev->functionality = I2C_FUNC_I2C |
+		I2C_FUNC_10BIT_ADDR |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+
 	dev->base = ioremap(mem->start, resource_size(mem));
 	if (dev->base == NULL) {
 		dev_err(&pdev->dev, "failure mapping io resources\n");
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 6/9] i2c-designware: move controller config to bus specific portion of driver
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (4 preceding siblings ...)
  2011-01-14 19:27   ` [PATCH 5/9] i2c-designware: move i2c functionality bit field to be adapter specific dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
       [not found]     ` <1295033256-30077-7-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-14 19:27   ` [PATCH 7/9] i2c-designware: Allow mixed endianness accesses dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
                     ` (3 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

With multiple I2C adapters possible in the system each running at
(possibly) different speeds we need to move the controller
configuration bit field to the adapter.

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/i2c-designware-core.c |    7 +++----
 drivers/i2c/busses/i2c-designware-core.h |    1 +
 drivers/i2c/busses/i2c-designware-pci.c  |   29 +++++++++++++++--------------
 drivers/i2c/busses/i2c-designware-plat.c |    2 ++
 4 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index c6a2b50..6723f9e 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -141,7 +141,7 @@ void
 i2c_dw_init(struct dw_i2c_dev *dev)
 {
 	u32 input_clock_khz;
-	u32 ic_con, hcnt, lcnt;
+	u32 hcnt, lcnt;
 
 	input_clock_khz = i2c_dw_clk_get_rate(dev);
 
@@ -183,9 +183,7 @@ i2c_dw_init(struct dw_i2c_dev *dev)
 	writel(0, dev->base + DW_IC_RX_TL);
 
 	/* configure the i2c master */
-	ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
-	writel(ic_con, dev->base + DW_IC_CON);
+	writel(dev->master_cfg, dev->base + DW_IC_CON);
 }
 EXPORT_SYMBOL(i2c_dw_init);
 
@@ -375,6 +373,7 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
 		return -EIO;
 }
 
+
 /*
  * Prepare controller for a transaction and call i2c_dw_xfer_msg
  */
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index e39a412..9aefe89 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -194,6 +194,7 @@ struct dw_i2c_dev {
 	int			irq;
 	struct i2c_adapter	adapter;
 	u32			functionality;
+	u32			master_cfg;
 	unsigned int		tx_fifo_depth;
 	unsigned int		rx_fifo_depth;
 };
diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
index 5d131ce..4e8681e 100644
--- a/drivers/i2c/busses/i2c-designware-pci.c
+++ b/drivers/i2c/busses/i2c-designware-pci.c
@@ -42,9 +42,6 @@
 #include "i2c-designware-core.h"
 
 #define DRIVER_NAME "i2c-designware-pci"
-#define STANDARD		0
-#define FAST			1
-#define HIGH			2
 
 enum dw_pci_ctl_id_t {
 	moorestown_0,
@@ -61,72 +58,76 @@ enum dw_pci_ctl_id_t {
 
 struct dw_pci_controller {
 	u32 bus_num;
-	u32 bus_speed;
+	u32 bus_cfg;
 	u32 tx_fifo_depth;
 	u32 rx_fifo_depth;
 	u32 clk_khz;
 };
 
+#define INTEL_MID_STD_CFG  (DW_IC_CON_MASTER |			\
+				DW_IC_CON_SLAVE_DISABLE |	\
+				DW_IC_CON_RESTART_EN)
+
 static struct  dw_pci_controller  dw_pci_controllers[] = {
 	[moorestown_0] = {
 		.bus_num     = 0,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[moorestown_1] = {
 		.bus_num     = 1,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[moorestown_2] = {
 		.bus_num     = 2,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[medfield_0] = {
 		.bus_num     = 0,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[medfield_1] = {
 		.bus_num     = 1,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[medfield_2] = {
 		.bus_num     = 2,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[medfield_3] = {
 		.bus_num     = 3,
-		.bus_speed   = STANDARD,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[medfield_4] = {
 		.bus_num     = 4,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
 	},
 	[medfield_5] = {
 		.bus_num     = 5,
-		.bus_speed   = FAST,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
 		.clk_khz      = 2500,
@@ -204,6 +205,7 @@ const struct pci_device_id *id)
 		I2C_FUNC_SMBUS_BYTE_DATA |
 		I2C_FUNC_SMBUS_WORD_DATA |
 		I2C_FUNC_SMBUS_I2C_BLOCK;
+	dev->master_cfg =  controller->bus_cfg;
 
 	pci_set_drvdata(pdev, dev);
 
@@ -212,7 +214,6 @@ const struct pci_device_id *id)
 
 	i2c_dw_init(dev);
 
-
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
 	adap->owner = THIS_MODULE;
diff --git a/drivers/i2c/busses/i2c-designware-plat.c b/drivers/i2c/busses/i2c-designware-plat.c
index cf157a4..843aa01 100644
--- a/drivers/i2c/busses/i2c-designware-plat.c
+++ b/drivers/i2c/busses/i2c-designware-plat.c
@@ -97,6 +97,8 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
 		I2C_FUNC_SMBUS_BYTE_DATA |
 		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;
 
 	dev->base = ioremap(mem->start, resource_size(mem));
 	if (dev->base == NULL) {
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 7/9] i2c-designware: Allow mixed endianness accesses
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (5 preceding siblings ...)
  2011-01-14 19:27   ` [PATCH 6/9] i2c-designware: move controller config to bus specific portion of driver dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
       [not found]     ` <1295033256-30077-8-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-14 19:27   ` [PATCH 8/9] i2c-designware-pci: Add runtime power management support dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
                     ` (2 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie,
	Jean-Hugues Deschenes

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Allows CPUs of a given endianness to access a dw controller of a different
endianness. Endianncess difference is detected at run time through the dw
component type register.

This is the hand application of a patch set by Jean-Hugues Deschenes
applied at the sugestion of Shinya Kuribayashi

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Jean-Hugues Deschenes <jean-hugues.deschenes-YGVykHU+fedBDgjK7y7TUQ@public.gmane.org>
---
 drivers/i2c/busses/i2c-designware-core.c |  116 +++++++++++++++++++-----------
 drivers/i2c/busses/i2c-designware-core.h |    9 ++-
 drivers/i2c/busses/i2c-designware-pci.c  |    4 +-
 drivers/i2c/busses/i2c-designware-plat.c |    5 +-
 4 files changed, 89 insertions(+), 45 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 6723f9e..746b4bb 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -48,6 +48,25 @@ static u32 i2c_dw_clk_get_rate(struct dw_i2c_dev *dev)
 #endif
 }
 
+u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+{
+	u32 value = readl(dev->base + offset);
+
+	if (dev->swab)
+		return swab32(value);
+	else
+		return value;
+}
+EXPORT_SYMBOL(dw_readl);
+
+void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+{
+	if (dev->swab)
+		b = swab32(b);
+
+	writel(b, dev->base + offset);
+}
+EXPORT_SYMBOL(dw_writel);
 
 static char *abort_sources[] = {
 	[ABRT_7B_ADDR_NOACK] =
@@ -137,16 +156,29 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
  * This function is called during I2C init function, and in case of timeout at
  * run time.
  */
-void
+int
 i2c_dw_init(struct dw_i2c_dev *dev)
 {
 	u32 input_clock_khz;
 	u32 hcnt, lcnt;
-
+	u32 reg;
 	input_clock_khz = i2c_dw_clk_get_rate(dev);
 
+	/* Configure register endianess access */
+	reg = dw_readl(dev, DW_IC_COMP_TYPE);
+	if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
+		dev->swab = 1;
+		reg = ___constant_swab32(DW_IC_COMP_TYPE_VALUE);
+	}
+
+	if (reg != DW_IC_COMP_TYPE_VALUE) {
+		dev_err(dev->dev, "Unknown Synopsys component type: "
+			"0x%08x\n", reg);
+		return -ENODEV;
+	}
+
 	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
+	dw_writel(dev, 0, DW_IC_ENABLE);
 
 	/* set standard and fast speed deviders for high/low periods */
 
@@ -160,8 +192,8 @@ i2c_dw_init(struct dw_i2c_dev *dev)
 				47,	/* tLOW = 4.7 us */
 				3,	/* tf = 0.3 us */
 				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_SS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_SS_SCL_LCNT);
+	dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
 	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
 	/* Fast-mode */
@@ -174,16 +206,17 @@ i2c_dw_init(struct dw_i2c_dev *dev)
 				13,	/* tLOW = 1.3 us */
 				3,	/* tf = 0.3 us */
 				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_FS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_FS_SCL_LCNT);
+	dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
 	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
 	/* Configure Tx/Rx FIFO threshold levels */
-	writel(dev->tx_fifo_depth - 1, dev->base + DW_IC_TX_TL);
-	writel(0, dev->base + DW_IC_RX_TL);
+	dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+	dw_writel(dev, 0, DW_IC_RX_TL);
 
 	/* configure the i2c master */
-	writel(dev->master_cfg, dev->base + DW_IC_CON);
+	dw_writel(dev, dev->master_cfg, DW_IC_CON);
+	return 0;
 }
 EXPORT_SYMBOL(i2c_dw_init);
 
@@ -195,7 +228,7 @@ i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
 {
 	int timeout = TIMEOUT;
 
-	while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+	while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
 		if (timeout <= 0) {
 			dev_warn(dev->dev, "timeout waiting for bus ready\n");
 			return -ETIMEDOUT;
@@ -214,24 +247,24 @@ i2c_dw_xfer_init(struct dw_i2c_dev *dev)
 	u32 ic_con;
 
 	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
+	dw_writel(dev, 0, DW_IC_ENABLE);
 
 	/* set the slave (target) address */
-	writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
+	dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
 
 	/* if the slave address is ten bit address, enable 10BITADDR */
-	ic_con = readl(dev->base + DW_IC_CON);
+	ic_con = dw_readl(dev, DW_IC_CON);
 	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
 		ic_con |= DW_IC_CON_10BITADDR_MASTER;
 	else
 		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
-	writel(ic_con, dev->base + DW_IC_CON);
+	dw_writel(dev, ic_con, DW_IC_CON);
 
 	/* Enable the adapter */
-	writel(1, dev->base + DW_IC_ENABLE);
+	dw_writel(dev, 1, DW_IC_ENABLE);
 
 	/* Enable interrupts */
-	writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
+	dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
 }
 
 /*
@@ -278,15 +311,15 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 			buf_len = msgs[dev->msg_write_idx].len;
 		}
 
-		tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR);
-		rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR);
+		tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
+		rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
 
 		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
 			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
-				writel(0x100, dev->base + DW_IC_DATA_CMD);
+				dw_writel(dev, 0x100, DW_IC_DATA_CMD);
 				rx_limit--;
 			} else
-				writel(*buf++, dev->base + DW_IC_DATA_CMD);
+				dw_writel(dev, *buf++, DW_IC_DATA_CMD);
 			tx_limit--; buf_len--;
 		}
 
@@ -311,7 +344,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 	if (dev->msg_err)
 		intr_mask = 0;
 
-	writel(intr_mask, dev->base + DW_IC_INTR_MASK);
+	dw_writel(dev, intr_mask, DW_IC_INTR_MASK);
 }
 
 void
@@ -335,10 +368,10 @@ i2c_dw_read(struct dw_i2c_dev *dev)
 			buf = dev->rx_buf;
 		}
 
-		rx_valid = readl(dev->base + DW_IC_RXFLR);
+		rx_valid = dw_readl(dev, DW_IC_RXFLR);
 
 		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
-			*buf++ = readl(dev->base + DW_IC_DATA_CMD);
+			*buf++ = dw_readl(dev, DW_IC_DATA_CMD);
 
 		if (len > 0) {
 			dev->status |= STATUS_READ_IN_PROGRESS;
@@ -422,7 +455,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 	/* no error */
 	if (likely(!dev->cmd_err)) {
 		/* Disable the adapter */
-		writel(0, dev->base + DW_IC_ENABLE);
+		dw_writel(dev, 0, DW_IC_ENABLE);
 		ret = num;
 		goto done;
 	}
@@ -458,47 +491,47 @@ u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 	 * in the IC_RAW_INTR_STAT register.
 	 *
 	 * That is,
-	 *   stat = readl(IC_INTR_STAT);
+	 *   stat = dw_readl(IC_INTR_STAT);
 	 * equals to,
-	 *   stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
+	 *   stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK);
 	 *
 	 * The raw version might be useful for debugging purposes.
 	 */
-	stat = readl(dev->base + DW_IC_INTR_STAT);
+	stat = dw_readl(dev, DW_IC_INTR_STAT);
 
 	/*
 	 * Do not use the IC_CLR_INTR register to clear interrupts, or
 	 * you'll miss some interrupts, triggered during the period from
-	 * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
+	 * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR).
 	 *
 	 * Instead, use the separately-prepared IC_CLR_* registers.
 	 */
 	if (stat & DW_IC_INTR_RX_UNDER)
-		readl(dev->base + DW_IC_CLR_RX_UNDER);
+		dw_readl(dev, DW_IC_CLR_RX_UNDER);
 	if (stat & DW_IC_INTR_RX_OVER)
-		readl(dev->base + DW_IC_CLR_RX_OVER);
+		dw_readl(dev, DW_IC_CLR_RX_OVER);
 	if (stat & DW_IC_INTR_TX_OVER)
-		readl(dev->base + DW_IC_CLR_TX_OVER);
+		dw_readl(dev, DW_IC_CLR_TX_OVER);
 	if (stat & DW_IC_INTR_RD_REQ)
-		readl(dev->base + DW_IC_CLR_RD_REQ);
+		dw_readl(dev, DW_IC_CLR_RD_REQ);
 	if (stat & DW_IC_INTR_TX_ABRT) {
 		/*
 		 * The IC_TX_ABRT_SOURCE register is cleared whenever
 		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
 		 */
-		dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
-		readl(dev->base + DW_IC_CLR_TX_ABRT);
+		dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE);
+		dw_readl(dev, DW_IC_CLR_TX_ABRT);
 	}
 	if (stat & DW_IC_INTR_RX_DONE)
-		readl(dev->base + DW_IC_CLR_RX_DONE);
+		dw_readl(dev, DW_IC_CLR_RX_DONE);
 	if (stat & DW_IC_INTR_ACTIVITY)
-		readl(dev->base + DW_IC_CLR_ACTIVITY);
+		dw_readl(dev, DW_IC_CLR_ACTIVITY);
 	if (stat & DW_IC_INTR_STOP_DET)
-		readl(dev->base + DW_IC_CLR_STOP_DET);
+		dw_readl(dev, DW_IC_CLR_STOP_DET);
 	if (stat & DW_IC_INTR_START_DET)
-		readl(dev->base + DW_IC_CLR_START_DET);
+		dw_readl(dev, DW_IC_CLR_START_DET);
 	if (stat & DW_IC_INTR_GEN_CALL)
-		readl(dev->base + DW_IC_CLR_GEN_CALL);
+		dw_readl(dev, DW_IC_CLR_GEN_CALL);
 
 	return stat;
 }
@@ -523,7 +556,7 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
 		 * Anytime TX_ABRT is set, the contents of the tx/rx
 		 * buffers are flushed.  Make sure to skip them.
 		 */
-		writel(0, dev->base + DW_IC_INTR_MASK);
+		dw_writel(dev, 0, DW_IC_INTR_MASK);
 		goto tx_aborted;
 	}
 
@@ -546,3 +579,4 @@ tx_aborted:
 	return IRQ_HANDLED;
 }
 EXPORT_SYMBOL(i2c_dw_isr);
+
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 9aefe89..148717f 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -68,8 +68,10 @@
 #define DW_IC_STATUS		0x70
 #define DW_IC_TXFLR		0x74
 #define DW_IC_RXFLR		0x78
-#define DW_IC_COMP_PARAM_1	0xf4
 #define DW_IC_TX_ABRT_SOURCE	0x80
+#define DW_IC_COMP_PARAM_1	0xf4
+#define DW_IC_COMP_TYPE		0xfc
+#define DW_IC_COMP_TYPE_VALUE	0x44570140
 
 #define DW_IC_CON_MASTER		0x1
 #define DW_IC_CON_SPEED_STD		0x2
@@ -192,6 +194,7 @@ struct dw_i2c_dev {
 	unsigned int		status;
 	u32			abort_source;
 	int			irq;
+	int			swab;
 	struct i2c_adapter	adapter;
 	u32			functionality;
 	u32			master_cfg;
@@ -200,8 +203,10 @@ struct dw_i2c_dev {
 };
 
 
-extern void i2c_dw_init(struct dw_i2c_dev *dev);
+extern int i2c_dw_init(struct dw_i2c_dev *dev);
 extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 		int num);
 extern u32 i2c_dw_func(struct i2c_adapter *adap);
 extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
+extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
+extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
index 4e8681e..1d57761 100644
--- a/drivers/i2c/busses/i2c-designware-pci.c
+++ b/drivers/i2c/busses/i2c-designware-pci.c
@@ -212,7 +212,9 @@ const struct pci_device_id *id)
 	dev->tx_fifo_depth = controller->tx_fifo_depth;
 	dev->rx_fifo_depth = controller->rx_fifo_depth;
 
-	i2c_dw_init(dev);
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
 
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
diff --git a/drivers/i2c/busses/i2c-designware-plat.c b/drivers/i2c/busses/i2c-designware-plat.c
index 843aa01..4b9fe33 100644
--- a/drivers/i2c/busses/i2c-designware-plat.c
+++ b/drivers/i2c/busses/i2c-designware-plat.c
@@ -112,7 +112,10 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
 		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
 		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
 	}
-	i2c_dw_init(dev);
+
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
 
 	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
 	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 8/9] i2c-designware-pci: Add runtime power management support
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (6 preceding siblings ...)
  2011-01-14 19:27   ` [PATCH 7/9] i2c-designware: Allow mixed endianness accesses dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
       [not found]     ` <1295033256-30077-9-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-14 19:27   ` [PATCH 9/9] i2c-designware: Support multiple cores using same ISR dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  2011-01-14 20:30   ` [PATCH RFC] Splitting i2c-designware.c to support PCI drivers Jean Delvare
  9 siblings, 1 reply; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/i2c-designware-core.c |   33 +++++++++-
 drivers/i2c/busses/i2c-designware-core.h |    2 +
 drivers/i2c/busses/i2c-designware-pci.c  |  111 +++++++++++++++++++++++++++---
 3 files changed, 135 insertions(+), 11 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 746b4bb..e8b354b 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -25,6 +25,7 @@
  * ----------------------------------------------------------------------------
  *
  */
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -37,6 +38,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include "i2c-designware-core.h"
 
 static u32 i2c_dw_clk_get_rate(struct dw_i2c_dev *dev)
@@ -418,6 +420,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
 
+	pm_runtime_get_sync(dev->dev);
 	mutex_lock(&dev->lock);
 
 	INIT_COMPLETION(dev->cmd_complete);
@@ -469,7 +472,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 done:
 	mutex_unlock(&dev->lock);
-
+	pm_runtime_put(dev->dev);
 	return ret;
 }
 EXPORT_SYMBOL(i2c_dw_xfer);
@@ -580,3 +583,31 @@ tx_aborted:
 }
 EXPORT_SYMBOL(i2c_dw_isr);
 
+void i2c_dw_enable(struct dw_i2c_dev *dev)
+{
+	/* Enable the adapter */
+	writel(1, dev->base + DW_IC_ENABLE);
+}
+EXPORT_SYMBOL(i2c_dw_enable);
+
+void i2c_dw_disable(struct dw_i2c_dev *i2c)
+{
+	/* Disable controller */
+	writel(0, i2c->base + DW_IC_ENABLE);
+
+	/* Disable all interupts */
+	writel(0x0000, i2c->base + DW_IC_INTR_MASK);
+
+	/* Clear all interrupts */
+	readl(i2c->base + DW_IC_CLR_INTR);
+	readl(i2c->base + DW_IC_CLR_STOP_DET);
+	readl(i2c->base + DW_IC_CLR_START_DET);
+	readl(i2c->base + DW_IC_CLR_ACTIVITY);
+	readl(i2c->base + DW_IC_CLR_TX_ABRT);
+	readl(i2c->base + DW_IC_CLR_RX_OVER);
+	readl(i2c->base + DW_IC_CLR_RX_UNDER);
+	readl(i2c->base + DW_IC_CLR_TX_OVER);
+	readl(i2c->base + DW_IC_CLR_RX_DONE);
+	readl(i2c->base + DW_IC_CLR_GEN_CALL);
+}
+EXPORT_SYMBOL(i2c_dw_disable);
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 148717f..e82b4dd 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -210,3 +210,5 @@ extern u32 i2c_dw_func(struct i2c_adapter *adap);
 extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
 extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
 extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+extern void i2c_dw_enable(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
index 1d57761..bea467e 100644
--- a/drivers/i2c/busses/i2c-designware-pci.c
+++ b/drivers/i2c/busses/i2c-designware-pci.c
@@ -138,7 +138,88 @@ static struct i2c_algorithm i2c_dw_algo = {
 	.functionality	= i2c_dw_func,
 };
 
-static int __devinit dw_i2c_pci_probe(struct pci_dev *pdev,
+static int i2c_dw_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+
+
+	i2c_dw_disable(i2c);
+
+	err = pci_save_state(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_save_state failed\n");
+		return err;
+	}
+
+	err = pci_set_power_state(pdev, PCI_D3hot);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int i2c_dw_pci_runtime_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	dev_dbg(dev, "PCI suspend called\n");
+	return i2c_dw_pci_suspend(pdev, PMSG_SUSPEND);
+}
+
+static int i2c_dw_pci_resume(struct pci_dev *pdev)
+{
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+	u32 enabled;
+
+	enabled = dw_readl(i2c, DW_IC_ENABLE);
+	if (enabled)
+		return 0;
+
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state() failed\n");
+		return err;
+	}
+
+	err = pci_restore_state(pdev);
+	if (err) {
+		dev_err(&pdev->dev, " pci_restore_state() failed\n");
+		return err;
+	}
+
+	i2c_dw_enable(i2c);
+	return 0;
+}
+
+static int i2c_dw_pci_runtime_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	dev_dbg(dev, "runtime_resume called\n");
+	return i2c_dw_pci_resume(pdev);
+}
+
+static int i2c_dw_pci_runtime_idle(struct device *dev)
+{
+	int err = pm_schedule_suspend(dev, 500);
+	dev_dbg(dev, "runtime_idle called\n");
+
+	if (err != 0)
+		return 0;
+	return -EBUSY;
+}
+
+
+
+static const struct dev_pm_ops i2c_dw_pm_ops = {
+	.runtime_suspend = i2c_dw_pci_runtime_suspend,
+	.runtime_resume = i2c_dw_pci_runtime_resume,
+	.runtime_idle = i2c_dw_pci_runtime_idle,
+};
+
+static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
 const struct pci_device_id *id)
 {
 	struct dw_i2c_dev *dev;
@@ -219,27 +300,28 @@ const struct pci_device_id *id)
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
 	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON;
-	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
-			sizeof(adap->name));
+	adap->class = 0;
 	adap->algo = &i2c_dw_algo;
 	adap->dev.parent = &pdev->dev;
-
 	adap->nr = controller->bus_num;
+	snprintf(adap->name, sizeof(adap->name), "i2c-dw-pci-%d",
+		adap->nr);
 
-	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
 	r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
 	if (r) {
 		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
 		goto err_iounmap;
 	}
 
+	dw_readl(dev, DW_IC_CLR_INTR);
+	dw_writel(dev, 0, DW_IC_INTR_MASK); /* disable IRQ */
 	r = i2c_add_numbered_adapter(adap);
 	if (r) {
 		dev_err(&pdev->dev, "failure adding adapter\n");
 		goto err_free_irq;
 	}
 
+	pm_runtime_enable(&pdev->dev);
 	return 0;
 
 err_free_irq:
@@ -255,11 +337,15 @@ exit:
 	return r;
 }
 
-static void __devexit dw_i2c_pci_remove(struct pci_dev *pdev)
+static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
 {
 	struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
 
-	writel(0, dev->base + DW_IC_ENABLE);
+	pm_runtime_get_noresume(&pdev->dev);
+	pm_runtime_forbid(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	i2c_dw_disable(dev);
 	pci_set_drvdata(pdev, NULL);
 	i2c_del_adapter(&dev->adapter);
 	put_device(&pdev->dev);
@@ -291,8 +377,13 @@ MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
 static struct pci_driver dw_i2c_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= i2_designware_pci_ids,
-	.probe		= dw_i2c_pci_probe,
-	.remove		= __devexit_p(dw_i2c_pci_remove),
+	.probe		= i2c_dw_pci_probe,
+	.remove		= __devexit_p(i2c_dw_pci_remove),
+	.resume		= i2c_dw_pci_resume,
+	.suspend	= i2c_dw_pci_suspend,
+	.driver		= {
+		.pm	= &i2c_dw_pm_ops,
+	},
 };
 
 static int __init dw_i2c_init_driver(void)
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 9/9] i2c-designware: Support multiple cores using same ISR
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (7 preceding siblings ...)
  2011-01-14 19:27   ` [PATCH 8/9] i2c-designware-pci: Add runtime power management support dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 19:27   ` dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  2011-01-14 20:30   ` [PATCH RFC] Splitting i2c-designware.c to support PCI drivers Jean Delvare
  9 siblings, 0 replies; 23+ messages in thread
From: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w @ 2011-01-14 19:27 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ, Dirk Brandewie

From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Add check to make sure that the core is enabled and has outstanding
interrupts. The activity bit is masked due to the fact that it will
stay active even after the contoller has bee disabled until the
contoller internal state machinces have settled.

Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/i2c-designware-core.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index e8b354b..c92feb5 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -546,10 +546,16 @@ u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
 {
 	struct dw_i2c_dev *dev = dev_id;
-	u32 stat;
+	u32 stat, enabled;
+
+	enabled = dw_readl(dev, DW_IC_ENABLE);
+	stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
+	dev_dbg(dev->dev, "%s:  %s enabled= 0x%x stat=0x%x\n", __func__,
+		dev->adapter.name, enabled, stat);
+	if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
+		return IRQ_NONE;
 
 	stat = i2c_dw_read_clear_intrbits(dev);
-	dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
 
 	if (stat & DW_IC_INTR_TX_ABRT) {
 		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC] Splitting i2c-designware.c to support PCI drivers
       [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (8 preceding siblings ...)
  2011-01-14 19:27   ` [PATCH 9/9] i2c-designware: Support multiple cores using same ISR dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
@ 2011-01-14 20:30   ` Jean Delvare
       [not found]     ` <20110114213007.58c8b237-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org>
  9 siblings, 1 reply; 23+ messages in thread
From: Jean Delvare @ 2011-01-14 20:30 UTC (permalink / raw)
  To: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ

Hi Dirk,

On Fri, 14 Jan 2011 11:27:27 -0800, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> 
> This patch set splits i2c-designware.c core and bus specific portions
> in to support the Designware core being behind a PCI device.
> 
> The Intel Moorsetown and Medfield SOC's are supported in the PCI
> portion of the driver.

We already have the i2c-intel-mid driver for Moorsetown and Medfield.
Why would we need another driver?

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC] Splitting i2c-designware.c to support PCI drivers
       [not found]     ` <20110114213007.58c8b237-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org>
@ 2011-01-14 21:48       ` Ben Dooks
       [not found]         ` <20110114214839.GC15795-SMNkleLxa3Z6Wcw2j4pizdi2O/JbrIOy@public.gmane.org>
  0 siblings, 1 reply; 23+ messages in thread
From: Ben Dooks @ 2011-01-14 21:48 UTC (permalink / raw)
  To: Jean Delvare
  Cc: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ

On Fri, Jan 14, 2011 at 09:30:07PM +0100, Jean Delvare wrote:
> Hi Dirk,
> 
> On Fri, 14 Jan 2011 11:27:27 -0800, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> > From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > 
> > This patch set splits i2c-designware.c core and bus specific portions
> > in to support the Designware core being behind a PCI device.
> > 
> > The Intel Moorsetown and Medfield SOC's are supported in the PCI
> > portion of the driver.
> 
> We already have the i2c-intel-mid driver for Moorsetown and Medfield.
> Why would we need another driver?

Maybe we could delete those and use this instead.

I wish I put my foot down and asked them to re-used the dw one otherwise
we'll just end up with driver creep....

-- 
Ben Dooks, ben-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org, http://www.fluff.org/ben/

Large Hadron Colada: A large Pina Colada that makes the universe disappear.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC] Splitting i2c-designware.c to support PCI drivers
       [not found]         ` <20110114214839.GC15795-SMNkleLxa3Z6Wcw2j4pizdi2O/JbrIOy@public.gmane.org>
@ 2011-01-17 16:06           ` Dirk Brandewie
       [not found]             ` <4D346909.6030503-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 23+ messages in thread
From: Dirk Brandewie @ 2011-01-17 16:06 UTC (permalink / raw)
  To: Ben Dooks
  Cc: Jean Delvare, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ

On 01/14/2011 01:48 PM, Ben Dooks wrote:
> On Fri, Jan 14, 2011 at 09:30:07PM +0100, Jean Delvare wrote:
>> Hi Dirk,
>>
>> On Fri, 14 Jan 2011 11:27:27 -0800, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
>>> From: Dirk Brandewie<dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>>
>>> This patch set splits i2c-designware.c core and bus specific portions
>>> in to support the Designware core being behind a PCI device.
>>>
>>> The Intel Moorsetown and Medfield SOC's are supported in the PCI
>>> portion of the driver.
>>
>> We already have the i2c-intel-mid driver for Moorsetown and Medfield.
>> Why would we need another driver?

I was tasked with fixing a couple of bugs i2c-intel-mid.c and adding support for 
another upcoming platform.  While I was coming up to speed on the driver I 
"discovered" the i2c-designware.c driver.  After talking with AlanC and Shinya 
it seemed like the right thing to do to merge the two drivers.  The patch set 
adds a parallel driver ATM moment until it get some good test.  Once it gets 
more test I plan on adding patches to remove i2c-intel-mid.c and update current 
i2c-designware.c driver to use the merged driver.

--Dirk
>
> Maybe we could delete those and use this instead.
>
> I wish I put my foot down and asked them to re-used the dw one otherwise
> we'll just end up with driver creep....
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH 7/9] i2c-designware: Allow mixed endianness accesses
       [not found]     ` <1295033256-30077-8-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-01-17 17:19       ` Jean-Hugues Deschenes
       [not found]         ` <2C61B7B7755780449CA3ED217819DA761BC7B3BD-VR+kULHyjlM/vpUtHNqADA@public.gmane.org>
  2011-01-25  2:45       ` Shinya Kuribayashi
  1 sibling, 1 reply; 23+ messages in thread
From: Jean-Hugues Deschenes @ 2011-01-17 17:19 UTC (permalink / raw)
  To: 'dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org',
	linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ

> +u32 dw_readl(struct dw_i2c_dev *dev, int offset)
> +{
> +	u32 value = readl(dev->base + offset);
> +
> +	if (dev->swab)
> +		return swab32(value);
> +	else
> +		return value;
> +}
> +EXPORT_SYMBOL(dw_readl);
> +
> +void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
> +{
> +	if (dev->swab)
> +		b = swab32(b);
> +
> +	writel(b, dev->base + offset);
> +}
> +EXPORT_SYMBOL(dw_writel);

I would just suggest to declare these accessors as static and avoid to
export the symbols, especially given their short names. Inlining these
short, frequently-accessed functions is attractive.

> +extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
> +extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);

Same here; I don't believe these lines are necessary.

jh

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC] Splitting i2c-designware.c to support PCI drivers
       [not found]             ` <4D346909.6030503-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-01-18 12:15               ` Jean Delvare
  0 siblings, 0 replies; 23+ messages in thread
From: Jean Delvare @ 2011-01-18 12:15 UTC (permalink / raw)
  To: Dirk Brandewie
  Cc: Ben Dooks, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	shinya.kuribayashi.px-zM6kxYcvzFBBDgjK7y7TUQ

Hi Dirk,

On Mon, 17 Jan 2011 08:06:33 -0800, Dirk Brandewie wrote:
> On 01/14/2011 01:48 PM, Ben Dooks wrote:
> > On Fri, Jan 14, 2011 at 09:30:07PM +0100, Jean Delvare wrote:
> >> Hi Dirk,
> >>
> >> On Fri, 14 Jan 2011 11:27:27 -0800, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> >>> From: Dirk Brandewie<dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >>>
> >>> This patch set splits i2c-designware.c core and bus specific portions
> >>> in to support the Designware core being behind a PCI device.
> >>>
> >>> The Intel Moorsetown and Medfield SOC's are supported in the PCI
> >>> portion of the driver.
> >>
> >> We already have the i2c-intel-mid driver for Moorsetown and Medfield.
> >> Why would we need another driver?
> 
> I was tasked with fixing a couple of bugs i2c-intel-mid.c and adding support for 
> another upcoming platform.  While I was coming up to speed on the driver I 
> "discovered" the i2c-designware.c driver.  After talking with AlanC and Shinya 
> it seemed like the right thing to do to merge the two drivers.  The patch set 
> adds a parallel driver ATM moment until it get some good test.  Once it gets 
> more test I plan on adding patches to remove i2c-intel-mid.c and update current 
> i2c-designware.c driver to use the merged driver.

OK, this makes a lot of sense then. You should have explained that
right away!

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/9] i2c-designware: Initial split of i2c-designware.c into core and bus specific parts
       [not found]     ` <1295033256-30077-3-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-01-25  1:58       ` Shinya Kuribayashi
       [not found]         ` <4D3E2E3F.1060506-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
  0 siblings, 1 reply; 23+ messages in thread
From: Shinya Kuribayashi @ 2011-01-25  1:58 UTC (permalink / raw)
  To: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, ben-linux-elnMNo+KYs3YtjvyW6yDsg

Hi,

On 1/15/2011 4:27 AM, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> 
> This patch splits i2c-designware.c into a core library and associated
> header file and two bus specific parts for platform bus and PCI bus.
> 
> Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/i2c/busses/Makefile              |    4 +
>  drivers/i2c/busses/i2c-designware-core.c |  541 ++++++++++++++++++++++++++++++
>  drivers/i2c/busses/i2c-designware-core.h |  204 +++++++++++
>  drivers/i2c/busses/i2c-designware-pci.c  |  183 ++++++++++
>  drivers/i2c/busses/i2c-designware-plat.c |  198 +++++++++++
>  5 files changed, 1130 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/busses/i2c-designware-core.c
>  create mode 100644 drivers/i2c/busses/i2c-designware-core.h
>  create mode 100644 drivers/i2c/busses/i2c-designware-pci.c
>  create mode 100644 drivers/i2c/busses/i2c-designware-plat.c
> 
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 0b9aa00..e1c0774 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -34,6 +34,10 @@ obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
>  obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
>  obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
>  obj-$(CONFIG_I2C_DESIGNWARE)	+= i2c-designware.o
> +obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c_dw_pci.o
> +i2c_dw_pci-objs := i2c-designware-pci.o i2c-designware-core.o
> +obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c_dw_plat.o
> +i2c_dw_plat-objs := i2c-designware-plat.o i2c-designware-core.o
>  obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
>  obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
>  obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o

It would be nice (and consistent) we could name these new modules as
simply 'i2c-designware-pci.ko' and 'i2c-designware-plat.ko'.  Is it
possible using <modulename>-objs build machinery?

> diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
> new file mode 100644
> index 0000000..9dca409
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-designware-core.c
> @@ -0,0 +1,541 @@
[...]

I've checked the diff between an existing i2c-designware.c and this
-core.c, and found that some unnecessary changes were made along with
-core.c duplication, which should be avoided as this patch is not
generated using git rename dection and hence hard to review.

>--- drivers/i2c/busses/i2c-designware.c	2011-01-22 23:07:42.571983857 +0900
>+++ drivers/i2c/busses/i2c-designware-core.c	2011-01-23 10:29:34.178022264 +0900
>@@ -170,57 +64,7 @@ static char *abort_sources[] = {
> 		"lost arbitration",
> };
> 
[...]
>-
>-static u32
>+u32
> i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
> {
> 	/*
>@@ -259,7 +103,7 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL,
> 		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
> }
> 
>-static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
>+u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
> {
> 	/*
> 	 * Conditional expression:

i2c_dw_scl_[hl]cnt() can be static.

>@@ -330,11 +175,13 @@ static void i2c_dw_init(struct dw_i2c_de
> 		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
> 	writel(ic_con, dev->base + DW_IC_CON);
> }
>+EXPORT_SYMBOL(i2c_dw_init);

Don't have to make it EXPORT_SYMBOL()-ed.  How about declaring it
with extern in -core.h ?  Am I missing something?

> 
> /*
>  * Waiting for bus not busy
>  */
>-static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
>+int
>+i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
> {
> 	int timeout = TIMEOUT;
> 

static.

>@@ -350,7 +197,8 @@ static int i2c_dw_wait_bus_not_busy(stru
> 	return 0;
> }
> 
>-static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
>+void
>+i2c_dw_xfer_init(struct dw_i2c_dev *dev)
> {
> 	struct i2c_msg *msgs = dev->msgs;
> 	u32 ic_con;

static.

>@@ -382,7 +230,7 @@ static void i2c_dw_xfer_init(struct dw_i
>  * messages into the tx buffer.  Even if the size of i2c_msg data is
>  * longer than the size of the tx buffer, it handles everything.
>  */
>-static void
>+void
> i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
> {
> 	struct i2c_msg *msgs = dev->msgs;

static.

>@@ -456,7 +304,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
> 	writel(intr_mask, dev->base + DW_IC_INTR_MASK);
> }
> 
>-static void
>+void
> i2c_dw_read(struct dw_i2c_dev *dev)
> {
> 	struct i2c_msg *msgs = dev->msgs;

static.

>@@ -492,7 +340,7 @@ i2c_dw_read(struct dw_i2c_dev *dev)
> 	}
> }
> 
>-static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
>+int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
> {
> 	unsigned long abort_source = dev->abort_source;
> 	int i;

static.

>@@ -518,7 +366,7 @@ static int i2c_dw_handle_tx_abort(struct
> /*
>  * Prepare controller for a transaction and call i2c_dw_xfer_msg
>  */
>-static int
>+int
> i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
> {
> 	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
>@@ -580,8 +428,9 @@ done:
> 
> 	return ret;
> }
>+EXPORT_SYMBOL(i2c_dw_xfer);
> 
>-static u32 i2c_dw_func(struct i2c_adapter *adap)
>+u32 i2c_dw_func(struct i2c_adapter *adap)
> {
> 	return	I2C_FUNC_I2C |
> 		I2C_FUNC_10BIT_ADDR |
>@@ -590,8 +439,9 @@ static u32 i2c_dw_func(struct i2c_adapte
> 		I2C_FUNC_SMBUS_WORD_DATA |
> 		I2C_FUNC_SMBUS_I2C_BLOCK;
> }
>+EXPORT_SYMBOL(i2c_dw_func);

Two functions above, i2c_dw_xfer() and i2c_dw_func(), shouldn't be
EXPORT_SYMBOL()-ed, either.

> 
>-static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
>+u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
> {
> 	u32 stat;
> 

static.

>@@ -650,7 +500,7 @@ static u32 i2c_dw_read_clear_intrbits(st
>  * Interrupt service routine. This gets called whenever an I2C interrupt
>  * occurs.
>  */
>-static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
>+irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
> {
> 	struct dw_i2c_dev *dev = dev_id;
> 	u32 stat;
[...]
>+EXPORT_SYMBOL(i2c_dw_isr);

No EXPORT_SYMBOL(). 

> diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
> new file mode 100644
> index 0000000..9558ef2
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-designware-core.h
> @@ -0,0 +1,204 @@
[...]
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/clk.h>
> +#include <linux/errno.h>
> +#include <linux/sched.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>

We could remove most of these headers, I've not sorted out yet.


> +#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
> +					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
> +					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
> +					 DW_IC_TX_ABRT_TXDATA_NOACK | \
> +					 DW_IC_TX_ABRT_GCALL_NOACK)
> +
> +

Two blank lines.

> +
> +extern void i2c_dw_init(struct dw_i2c_dev *dev);
> +extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
> +		int num);
> +extern u32 i2c_dw_func(struct i2c_adapter *adap);
> +extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);

Yeah, we have these in place.

> diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
> new file mode 100644
> index 0000000..11185b2
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-designware-pci.c
> @@ -0,0 +1,183 @@
[...]
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/errno.h>
> +#include <linux/sched.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include "i2c-designware-core.h"

I guess we could omit more headers.

> diff --git a/drivers/i2c/busses/i2c-designware-plat.c b/drivers/i2c/busses/i2c-designware-plat.c
> new file mode 100644
> index 0000000..b8e5aa4
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-designware-plat.c
> @@ -0,0 +1,198 @@
[...]
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/clk.h>
> +#include <linux/errno.h>
> +#include <linux/sched.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +
> +#include "i2c-designware-core.h"

Same here.

And the following is the diff between -pci.c and -plat.c.

>--- drivers/i2c/busses/i2c-designware-pci.c	2011-01-23 10:29:34.178022264 +0900
>+++ drivers/i2c/busses/i2c-designware-plat.c	2011-01-23 10:29:34.190022267 +0900
>@@ -25,11 +25,11 @@
>  * ----------------------------------------------------------------------------
>  *
>  */
>-
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/delay.h>
> #include <linux/i2c.h>
>+#include <linux/clk.h>
> #include <linux/errno.h>
> #include <linux/sched.h>
> #include <linux/err.h>
>@@ -37,6 +37,7 @@
> #include <linux/platform_device.h>
> #include <linux/io.h>
> #include <linux/slab.h>
>+
> #include "i2c-designware-core.h"
> 
> static struct i2c_algorithm i2c_dw_algo = {
>@@ -83,6 +84,12 @@ static int __devinit dw_i2c_probe(struct
> 	dev->irq = irq;
> 	platform_set_drvdata(pdev, dev);
> 
>+	dev->clk = clk_get(&pdev->dev, NULL);
>+	if (IS_ERR(dev->clk)) {
>+		r = -ENODEV;
>+		goto err_free_mem;
>+	}
>+	clk_enable(dev->clk);
> 
> 	dev->base = ioremap(mem->start, resource_size(mem));
> 	if (dev->base == NULL) {
>@@ -127,6 +134,10 @@ err_free_irq:
> 	free_irq(dev->irq, dev);
> err_iounmap:
> 	iounmap(dev->base);
>+err_unuse_clocks:
>+	clk_disable(dev->clk);
>+	clk_put(dev->clk);
>+	dev->clk = NULL;
> err_free_mem:
> 	platform_set_drvdata(pdev, NULL);
> 	put_device(&pdev->dev);
>@@ -146,6 +157,10 @@ static int __devexit dw_i2c_remove(struc
> 	i2c_del_adapter(&dev->adapter);
> 	put_device(&pdev->dev);
> 
>+	clk_disable(dev->clk);
>+	clk_put(dev->clk);
>+	dev->clk = NULL;
>+
> 	writel(0, dev->base + DW_IC_ENABLE);
> 	free_irq(dev->irq, dev);
> 	kfree(dev);

-pci.c is primary meant for the Intel Moorsetown and Medfield SoCs
as of now, and we're fine with removing clkdev API dependencies from
-pci.c file.

That said, two concerns.  First, clkdev API support isn't related to
PCI support, so it might be reasonable to disable clk_ procedures appear
in the above patch simply using #ifdef HAVE_CLK, rather than completely
removed.  The other is, how about separating such changes into another
commit, or cook it along with PATCH 3/9?

I'll follow up other patches later.
-- 
Shinya Kuribayashi
Renesas Electronics

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] i2c-designware: move i2c functionality bit field to be adapter specific
       [not found]     ` <1295033256-30077-6-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-01-25  2:07       ` Shinya Kuribayashi
  0 siblings, 0 replies; 23+ messages in thread
From: Shinya Kuribayashi @ 2011-01-25  2:07 UTC (permalink / raw)
  To: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, ben-linux-elnMNo+KYs3YtjvyW6yDsg

On 1/15/2011 4:27 AM, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> 
> The functionality of the adapter depends on the configuration of the
> IP block at silicon compile time and is adapter specific.

Good point.

> diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
> index 00717df..5d131ce 100644
> --- a/drivers/i2c/busses/i2c-designware-pci.c
> +++ b/drivers/i2c/busses/i2c-designware-pci.c
> @@ -199,6 +199,12 @@ const struct pci_device_id *id)
>  	dev->clk_khz = controller->clk_khz;
>  	dev->base = base;
>  	dev->dev = get_device(&pdev->dev);
> +	dev->functionality = I2C_FUNC_I2C |
> +		I2C_FUNC_SMBUS_BYTE |
> +		I2C_FUNC_SMBUS_BYTE_DATA |
> +		I2C_FUNC_SMBUS_WORD_DATA |
> +		I2C_FUNC_SMBUS_I2C_BLOCK;
> +
>  	pci_set_drvdata(pdev, dev);
>  
>  	dev->tx_fifo_depth = controller->tx_fifo_depth;

I'd prefer to have them aligned.

> diff --git a/drivers/i2c/busses/i2c-designware-plat.c b/drivers/i2c/busses/i2c-designware-plat.c
> index b8e5aa4..cf157a4 100644
> --- a/drivers/i2c/busses/i2c-designware-plat.c
> +++ b/drivers/i2c/busses/i2c-designware-plat.c
> @@ -91,6 +91,13 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
>  	}
>  	clk_enable(dev->clk);
>  
> +	dev->functionality = I2C_FUNC_I2C |
> +		I2C_FUNC_10BIT_ADDR |
> +		I2C_FUNC_SMBUS_BYTE |
> +		I2C_FUNC_SMBUS_BYTE_DATA |
> +		I2C_FUNC_SMBUS_WORD_DATA |
> +		I2C_FUNC_SMBUS_I2C_BLOCK;
> +
>  	dev->base = ioremap(mem->start, resource_size(mem));
>  	if (dev->base == NULL) {
>  		dev_err(&pdev->dev, "failure mapping io resources\n");

Ditto.
-- 
Shinya Kuribayashi
Renesas Electronics

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 6/9] i2c-designware: move controller config to bus specific portion of driver
       [not found]     ` <1295033256-30077-7-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-01-25  2:22       ` Shinya Kuribayashi
  0 siblings, 0 replies; 23+ messages in thread
From: Shinya Kuribayashi @ 2011-01-25  2:22 UTC (permalink / raw)
  To: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, ben-linux-elnMNo+KYs3YtjvyW6yDsg

On 1/15/2011 4:27 AM, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> 
> With multiple I2C adapters possible in the system each running at
> (possibly) different speeds we need to move the controller
> configuration bit field to the adapter.

This is also a good first step to support per-bus basis I2C bus-speed
configuration, because current i2c-designware driver is going to
configure all I2C busses with the same speed settings, unfortunately.

> @@ -375,6 +373,7 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
>  		return -EIO;
>  }
>  
> +
>  /*
>   * Prepare controller for a transaction and call i2c_dw_xfer_msg
>   */

!

> @@ -212,7 +214,6 @@ const struct pci_device_id *id)
>  
>  	i2c_dw_init(dev);
>  
> -
>  	adap = &dev->adapter;
>  	i2c_set_adapdata(adap, dev);
>  	adap->owner = THIS_MODULE;

!

As talked with Dirk-san before, this patch improves a situation at
PCI driver side only, and we need to come up with a way for platform
side in the future!
-- 
Shinya Kuribayashi
Renesas Electronics

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 7/9] i2c-designware: Allow mixed endianness accesses
       [not found]         ` <2C61B7B7755780449CA3ED217819DA761BC7B3BD-VR+kULHyjlM/vpUtHNqADA@public.gmane.org>
@ 2011-01-25  2:28           ` Shinya Kuribayashi
       [not found]             ` <4D3E3546.80806-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
  0 siblings, 1 reply; 23+ messages in thread
From: Shinya Kuribayashi @ 2011-01-25  2:28 UTC (permalink / raw)
  To: Jean-Hugues Deschenes
  Cc: 'dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org',
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg

On 1/18/2011 2:19 AM, Jean-Hugues Deschenes wrote:
>> +u32 dw_readl(struct dw_i2c_dev *dev, int offset)
>> +{
>> +	u32 value = readl(dev->base + offset);
>> +
>> +	if (dev->swab)
>> +		return swab32(value);
>> +	else
>> +		return value;
>> +}
>> +EXPORT_SYMBOL(dw_readl);
>> +
>> +void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
>> +{
>> +	if (dev->swab)
>> +		b = swab32(b);
>> +
>> +	writel(b, dev->base + offset);
>> +}
>> +EXPORT_SYMBOL(dw_writel);
> 
> I would just suggest to declare these accessors as static and avoid to
> export the symbols, especially given their short names. Inlining these
> short, frequently-accessed functions is attractive.
> 
>> +extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
>> +extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
> 
> Same here; I don't believe these lines are necessary.

Ack.

Furthermore, I'd like to see this patch at the start at Dirk-san's
patchset.  We don't want to make a already proposed patch adapted to
a modified driver.
-- 
Shinya Kuribayashi
Renesas Electronics

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 7/9] i2c-designware: Allow mixed endianness accesses
       [not found]     ` <1295033256-30077-8-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-01-17 17:19       ` Jean-Hugues Deschenes
@ 2011-01-25  2:45       ` Shinya Kuribayashi
  1 sibling, 0 replies; 23+ messages in thread
From: Shinya Kuribayashi @ 2011-01-25  2:45 UTC (permalink / raw)
  To: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, Jean-Hugues Deschenes

On 1/15/2011 4:27 AM, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> From: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> 
> Allows CPUs of a given endianness to access a dw controller of a different
> endianness. Endianncess difference is detected at run time through the dw
> component type register.
> 
> This is the hand application of a patch set by Jean-Hugues Deschenes
> applied at the sugestion of Shinya Kuribayashi
> 
> Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> CC: Jean-Hugues Deschenes <jean-hugues.deschenes-YGVykHU+fedBDgjK7y7TUQ@public.gmane.org>
> ---
>  drivers/i2c/busses/i2c-designware-core.c |  116 +++++++++++++++++++-----------
>  drivers/i2c/busses/i2c-designware-core.h |    9 ++-
>  drivers/i2c/busses/i2c-designware-pci.c  |    4 +-
>  drivers/i2c/busses/i2c-designware-plat.c |    5 +-
>  4 files changed, 89 insertions(+), 45 deletions(-)
> 

Here Dirk-san makes an improvement against a proposed patch from Jean;
moving the component type cheking routines from _probe() function
into i2c_dw_init().  I'd propose to make it as separate patch(es).

> diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
> index 6723f9e..746b4bb 100644
> --- a/drivers/i2c/busses/i2c-designware-core.c
> +++ b/drivers/i2c/busses/i2c-designware-core.c
> @@ -137,16 +156,29 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
>   * This function is called during I2C init function, and in case of timeout at
>   * run time.
>   */
> -void
> +int
>  i2c_dw_init(struct dw_i2c_dev *dev)
>  {
>  	u32 input_clock_khz;
>  	u32 hcnt, lcnt;
> -
> +	u32 reg;
>  	input_clock_khz = i2c_dw_clk_get_rate(dev);
>  
> +	/* Configure register endianess access */
> +	reg = dw_readl(dev, DW_IC_COMP_TYPE);
> +	if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
> +		dev->swab = 1;
> +		reg = ___constant_swab32(DW_IC_COMP_TYPE_VALUE);
> +	}
> +
> +	if (reg != DW_IC_COMP_TYPE_VALUE) {
> +		dev_err(dev->dev, "Unknown Synopsys component type: "
> +			"0x%08x\n", reg);
> +		return -ENODEV;
> +	}
> +
>  	/* Disable the adapter */
> -	writel(0, dev->base + DW_IC_ENABLE);
> +	dw_writel(dev, 0, DW_IC_ENABLE);
>  
>  	/* set standard and fast speed deviders for high/low periods */
>  

Two changes are combined into one patch, while they're separate in
the original Jean's patch.  I'd like to see Jean-san's patches as-is
as far as possible.
-- 
Shinya Kuribayashi
Renesas Electronics

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 8/9] i2c-designware-pci: Add runtime power management support
       [not found]     ` <1295033256-30077-9-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-01-25  3:00       ` Shinya Kuribayashi
  0 siblings, 0 replies; 23+ messages in thread
From: Shinya Kuribayashi @ 2011-01-25  3:00 UTC (permalink / raw)
  To: dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, ben-linux-elnMNo+KYs3YtjvyW6yDsg

On 1/15/2011 4:27 AM, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
> index 746b4bb..e8b354b 100644
> --- a/drivers/i2c/busses/i2c-designware-core.c
> +++ b/drivers/i2c/busses/i2c-designware-core.c
> @@ -580,3 +583,31 @@ tx_aborted:
>  }
>  EXPORT_SYMBOL(i2c_dw_isr);
>  
> +void i2c_dw_enable(struct dw_i2c_dev *dev)
> +{
> +	/* Enable the adapter */
> +	writel(1, dev->base + DW_IC_ENABLE);
> +}
> +EXPORT_SYMBOL(i2c_dw_enable);

Having enable/disable wrapper functions is good and promissing, as
that helps us to avoid direct references to the IC_ENABLE register
from -pci.c and -plat.c.

> +void i2c_dw_disable(struct dw_i2c_dev *i2c)
> +{
> +	/* Disable controller */
> +	writel(0, i2c->base + DW_IC_ENABLE);
> +
> +	/* Disable all interupts */
> +	writel(0x0000, i2c->base + DW_IC_INTR_MASK);
> +
> +	/* Clear all interrupts */
> +	readl(i2c->base + DW_IC_CLR_INTR);
> +	readl(i2c->base + DW_IC_CLR_STOP_DET);
> +	readl(i2c->base + DW_IC_CLR_START_DET);
> +	readl(i2c->base + DW_IC_CLR_ACTIVITY);
> +	readl(i2c->base + DW_IC_CLR_TX_ABRT);
> +	readl(i2c->base + DW_IC_CLR_RX_OVER);
> +	readl(i2c->base + DW_IC_CLR_RX_UNDER);
> +	readl(i2c->base + DW_IC_CLR_TX_OVER);
> +	readl(i2c->base + DW_IC_CLR_RX_DONE);
> +	readl(i2c->base + DW_IC_CLR_GEN_CALL);
> +}
> +EXPORT_SYMBOL(i2c_dw_disable);

Note that when you read the IC_CLR_INTR register, all interrupt status
bits asserted at that time will be cleared, so no need to read
remaining the IC_CLR_STOP_DET..IC_CLER_GEN_CALL registers.

By the way, I have one patch regarding safely shutdown the controller.
Will send a patch to Dirk later.

> diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
> index 1d57761..bea467e 100644
> --- a/drivers/i2c/busses/i2c-designware-pci.c
> +++ b/drivers/i2c/busses/i2c-designware-pci.c
[...]
> +static int i2c_dw_pci_resume(struct pci_dev *pdev)
> +{
> +	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
> +	int err;
> +	u32 enabled;
> +
> +	enabled = dw_readl(i2c, DW_IC_ENABLE);
> +	if (enabled)
> +		return 0;

Hmm, we still have a direct reference to IC_ENABLE here.

> @@ -219,27 +300,28 @@ const struct pci_device_id *id)
>  	adap = &dev->adapter;
>  	i2c_set_adapdata(adap, dev);
>  	adap->owner = THIS_MODULE;
> -	adap->class = I2C_CLASS_HWMON;
> -	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
> -			sizeof(adap->name));
> +	adap->class = 0;
>  	adap->algo = &i2c_dw_algo;
>  	adap->dev.parent = &pdev->dev;
> -
>  	adap->nr = controller->bus_num;
> +	snprintf(adap->name, sizeof(adap->name), "i2c-dw-pci-%d",
> +		adap->nr);
>  
> -	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
>  	r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
>  	if (r) {
>  		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
>  		goto err_iounmap;
>  	}
>  
> +	dw_readl(dev, DW_IC_CLR_INTR);
> +	dw_writel(dev, 0, DW_IC_INTR_MASK); /* disable IRQ */

Replacing with i2c_dw_disable()?

>  	r = i2c_add_numbered_adapter(adap);
>  	if (r) {
>  		dev_err(&pdev->dev, "failure adding adapter\n");
>  		goto err_free_irq;
>  	}
>  
> +	pm_runtime_enable(&pdev->dev);
>  	return 0;
>  
>  err_free_irq:
-- 
Shinya Kuribayashi
Renesas Electronics

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/9] i2c-designware: Initial split of i2c-designware.c into core and bus specific parts
       [not found]         ` <4D3E2E3F.1060506-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
@ 2011-01-25 15:26           ` Dirk Brandewie
  0 siblings, 0 replies; 23+ messages in thread
From: Dirk Brandewie @ 2011-01-25 15:26 UTC (permalink / raw)
  To: Shinya Kuribayashi
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, ben-linux-elnMNo+KYs3YtjvyW6yDsg

On 01/24/2011 05:58 PM, Shinya Kuribayashi wrote:
> Hi,
>
> On 1/15/2011 4:27 AM, dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
>> From: Dirk Brandewie<dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>
>> This patch splits i2c-designware.c into a core library and associated
>> header file and two bus specific parts for platform bus and PCI bus.
>>
>> Signed-off-by: Dirk Brandewie<dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>>   drivers/i2c/busses/Makefile              |    4 +
>>   drivers/i2c/busses/i2c-designware-core.c |  541 ++++++++++++++++++++++++++++++
>>   drivers/i2c/busses/i2c-designware-core.h |  204 +++++++++++
>>   drivers/i2c/busses/i2c-designware-pci.c  |  183 ++++++++++
>>   drivers/i2c/busses/i2c-designware-plat.c |  198 +++++++++++
>>   5 files changed, 1130 insertions(+), 0 deletions(-)
>>   create mode 100644 drivers/i2c/busses/i2c-designware-core.c
>>   create mode 100644 drivers/i2c/busses/i2c-designware-core.h
>>   create mode 100644 drivers/i2c/busses/i2c-designware-pci.c
>>   create mode 100644 drivers/i2c/busses/i2c-designware-plat.c
>>
>> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
>> index 0b9aa00..e1c0774 100644
>> --- a/drivers/i2c/busses/Makefile
>> +++ b/drivers/i2c/busses/Makefile
>> @@ -34,6 +34,10 @@ obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
>>   obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
>>   obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
>>   obj-$(CONFIG_I2C_DESIGNWARE)	+= i2c-designware.o
>> +obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c_dw_pci.o
>> +i2c_dw_pci-objs := i2c-designware-pci.o i2c-designware-core.o
>> +obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c_dw_plat.o
>> +i2c_dw_plat-objs := i2c-designware-plat.o i2c-designware-core.o
>>   obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
>>   obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
>>   obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
>
> It would be nice (and consistent) we could name these new modules as
> simply 'i2c-designware-pci.ko' and 'i2c-designware-plat.ko'.  Is it
> possible using<modulename>-objs build machinery?

I will look into it, I just used a name that made sense (to me) at the time :-)

>
>> diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
>> new file mode 100644
>> index 0000000..9dca409
>> --- /dev/null
>> +++ b/drivers/i2c/busses/i2c-designware-core.c
>> @@ -0,0 +1,541 @@
> [...]
>
> I've checked the diff between an existing i2c-designware.c and this
> -core.c, and found that some unnecessary changes were made along with
> -core.c duplication, which should be avoided as this patch is not
> generated using git rename dection and hence hard to review.
>
Will fix when I re-roll the patch set

>> --- drivers/i2c/busses/i2c-designware.c	2011-01-22 23:07:42.571983857 +0900
>> +++ drivers/i2c/busses/i2c-designware-core.c	2011-01-23 10:29:34.178022264 +0900
>> @@ -170,57 +64,7 @@ static char *abort_sources[] = {
>> 		"lost arbitration",
>> };
>>
> [...]
>> -
>> -static u32
>> +u32
>> i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
>> {
>> 	/*
>> @@ -259,7 +103,7 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL,
>> 		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
>> }
>>
>> -static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
>> +u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
>> {
>> 	/*
>> 	 * Conditional expression:
>
> i2c_dw_scl_[hl]cnt() can be static.
>
Yep
>> @@ -330,11 +175,13 @@ static void i2c_dw_init(struct dw_i2c_de
>> 		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
>> 	writel(ic_con, dev->base + DW_IC_CON);
>> }
>> +EXPORT_SYMBOL(i2c_dw_init);
>
> Don't have to make it EXPORT_SYMBOL()-ed.  How about declaring it
> with extern in -core.h ?  Am I missing something?

Nope I will fix

>
>>
>> /*
>>   * Waiting for bus not busy
>>   */
>> -static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
>> +int
>> +i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
>> {
>> 	int timeout = TIMEOUT;
>>
>
> static.
>
>> @@ -350,7 +197,8 @@ static int i2c_dw_wait_bus_not_busy(stru
>> 	return 0;
>> }
>>
>> -static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
>> +void
>> +i2c_dw_xfer_init(struct dw_i2c_dev *dev)
>> {
>> 	struct i2c_msg *msgs = dev->msgs;
>> 	u32 ic_con;
>
> static.
>
>> @@ -382,7 +230,7 @@ static void i2c_dw_xfer_init(struct dw_i
>>   * messages into the tx buffer.  Even if the size of i2c_msg data is
>>   * longer than the size of the tx buffer, it handles everything.
>>   */
>> -static void
>> +void
>> i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
>> {
>> 	struct i2c_msg *msgs = dev->msgs;
>
> static.
>
>> @@ -456,7 +304,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
>> 	writel(intr_mask, dev->base + DW_IC_INTR_MASK);
>> }
>>
>> -static void
>> +void
>> i2c_dw_read(struct dw_i2c_dev *dev)
>> {
>> 	struct i2c_msg *msgs = dev->msgs;
>
> static.
>
>> @@ -492,7 +340,7 @@ i2c_dw_read(struct dw_i2c_dev *dev)
>> 	}
>> }
>>
>> -static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
>> +int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
>> {
>> 	unsigned long abort_source = dev->abort_source;
>> 	int i;
>
> static.
>
>> @@ -518,7 +366,7 @@ static int i2c_dw_handle_tx_abort(struct
>> /*
>>   * Prepare controller for a transaction and call i2c_dw_xfer_msg
>>   */
>> -static int
>> +int
>> i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>> {
>> 	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
>> @@ -580,8 +428,9 @@ done:
>>
>> 	return ret;
>> }
>> +EXPORT_SYMBOL(i2c_dw_xfer);
>>
>> -static u32 i2c_dw_func(struct i2c_adapter *adap)
>> +u32 i2c_dw_func(struct i2c_adapter *adap)
>> {
>> 	return	I2C_FUNC_I2C |
>> 		I2C_FUNC_10BIT_ADDR |
>> @@ -590,8 +439,9 @@ static u32 i2c_dw_func(struct i2c_adapte
>> 		I2C_FUNC_SMBUS_WORD_DATA |
>> 		I2C_FUNC_SMBUS_I2C_BLOCK;
>> }
>> +EXPORT_SYMBOL(i2c_dw_func);
>
> Two functions above, i2c_dw_xfer() and i2c_dw_func(), shouldn't be
> EXPORT_SYMBOL()-ed, either.
>
Ack

>>
>> -static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
>> +u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
>> {
>> 	u32 stat;
>>
>
> static.
>
>> @@ -650,7 +500,7 @@ static u32 i2c_dw_read_clear_intrbits(st
>>   * Interrupt service routine. This gets called whenever an I2C interrupt
>>   * occurs.
>>   */
>> -static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
>> +irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
>> {
>> 	struct dw_i2c_dev *dev = dev_id;
>> 	u32 stat;
> [...]
>> +EXPORT_SYMBOL(i2c_dw_isr);
>
> No EXPORT_SYMBOL().
>
>> diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
>> new file mode 100644
>> index 0000000..9558ef2
>> --- /dev/null
>> +++ b/drivers/i2c/busses/i2c-designware-core.h
>> @@ -0,0 +1,204 @@
> [...]
>> +#include<linux/kernel.h>
>> +#include<linux/module.h>
>> +#include<linux/delay.h>
>> +#include<linux/i2c.h>
>> +#include<linux/clk.h>
>> +#include<linux/errno.h>
>> +#include<linux/sched.h>
>> +#include<linux/err.h>
>> +#include<linux/interrupt.h>
>> +#include<linux/platform_device.h>
>> +#include<linux/io.h>
>> +#include<linux/slab.h>
>
> We could remove most of these headers, I've not sorted out yet.
>
>
>> +#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
>> +					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
>> +					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
>> +					 DW_IC_TX_ABRT_TXDATA_NOACK | \
>> +					 DW_IC_TX_ABRT_GCALL_NOACK)
>> +
>> +
>
> Two blank lines.
>
>> +
>> +extern void i2c_dw_init(struct dw_i2c_dev *dev);
>> +extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
>> +		int num);
>> +extern u32 i2c_dw_func(struct i2c_adapter *adap);
>> +extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
>
> Yeah, we have these in place.
>
>> diff --git a/drivers/i2c/busses/i2c-designware-pci.c b/drivers/i2c/busses/i2c-designware-pci.c
>> new file mode 100644
>> index 0000000..11185b2
>> --- /dev/null
>> +++ b/drivers/i2c/busses/i2c-designware-pci.c
>> @@ -0,0 +1,183 @@
> [...]
>> +#include<linux/kernel.h>
>> +#include<linux/module.h>
>> +#include<linux/delay.h>
>> +#include<linux/i2c.h>
>> +#include<linux/errno.h>
>> +#include<linux/sched.h>
>> +#include<linux/err.h>
>> +#include<linux/interrupt.h>
>> +#include<linux/platform_device.h>
>> +#include<linux/io.h>
>> +#include<linux/slab.h>
>> +#include "i2c-designware-core.h"
>
> I guess we could omit more headers.
>
>> diff --git a/drivers/i2c/busses/i2c-designware-plat.c b/drivers/i2c/busses/i2c-designware-plat.c
>> new file mode 100644
>> index 0000000..b8e5aa4
>> --- /dev/null
>> +++ b/drivers/i2c/busses/i2c-designware-plat.c
>> @@ -0,0 +1,198 @@
> [...]
>> +#include<linux/kernel.h>
>> +#include<linux/module.h>
>> +#include<linux/delay.h>
>> +#include<linux/i2c.h>
>> +#include<linux/clk.h>
>> +#include<linux/errno.h>
>> +#include<linux/sched.h>
>> +#include<linux/err.h>
>> +#include<linux/interrupt.h>
>> +#include<linux/platform_device.h>
>> +#include<linux/io.h>
>> +#include<linux/slab.h>
>> +
>> +#include "i2c-designware-core.h"
>
> Same here.
>
> And the following is the diff between -pci.c and -plat.c.
>
>> --- drivers/i2c/busses/i2c-designware-pci.c	2011-01-23 10:29:34.178022264 +0900
>> +++ drivers/i2c/busses/i2c-designware-plat.c	2011-01-23 10:29:34.190022267 +0900
>> @@ -25,11 +25,11 @@
>>   * ----------------------------------------------------------------------------
>>   *
>>   */
>> -
>> #include<linux/kernel.h>
>> #include<linux/module.h>
>> #include<linux/delay.h>
>> #include<linux/i2c.h>
>> +#include<linux/clk.h>
>> #include<linux/errno.h>
>> #include<linux/sched.h>
>> #include<linux/err.h>
>> @@ -37,6 +37,7 @@
>> #include<linux/platform_device.h>
>> #include<linux/io.h>
>> #include<linux/slab.h>
>> +
>> #include "i2c-designware-core.h"
>>
>> static struct i2c_algorithm i2c_dw_algo = {
>> @@ -83,6 +84,12 @@ static int __devinit dw_i2c_probe(struct
>> 	dev->irq = irq;
>> 	platform_set_drvdata(pdev, dev);
>>
>> +	dev->clk = clk_get(&pdev->dev, NULL);
>> +	if (IS_ERR(dev->clk)) {
>> +		r = -ENODEV;
>> +		goto err_free_mem;
>> +	}
>> +	clk_enable(dev->clk);
>>
>> 	dev->base = ioremap(mem->start, resource_size(mem));
>> 	if (dev->base == NULL) {
>> @@ -127,6 +134,10 @@ err_free_irq:
>> 	free_irq(dev->irq, dev);
>> err_iounmap:
>> 	iounmap(dev->base);
>> +err_unuse_clocks:
>> +	clk_disable(dev->clk);
>> +	clk_put(dev->clk);
>> +	dev->clk = NULL;
>> err_free_mem:
>> 	platform_set_drvdata(pdev, NULL);
>> 	put_device(&pdev->dev);
>> @@ -146,6 +157,10 @@ static int __devexit dw_i2c_remove(struc
>> 	i2c_del_adapter(&dev->adapter);
>> 	put_device(&pdev->dev);
>>
>> +	clk_disable(dev->clk);
>> +	clk_put(dev->clk);
>> +	dev->clk = NULL;
>> +
>> 	writel(0, dev->base + DW_IC_ENABLE);
>> 	free_irq(dev->irq, dev);
>> 	kfree(dev);
>
> -pci.c is primary meant for the Intel Moorsetown and Medfield SoCs
> as of now, and we're fine with removing clkdev API dependencies from
> -pci.c file.
>
> That said, two concerns.  First, clkdev API support isn't related to
> PCI support, so it might be reasonable to disable clk_ procedures appear
> in the above patch simply using #ifdef HAVE_CLK, rather than completely
> removed.  The other is, how about separating such changes into another
> commit, or cook it along with PATCH 3/9?
>
I will rework this so the clk infrasttucture can be used with PCI.

> I'll follow up other patches later.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 7/9] i2c-designware: Allow mixed endianness accesses
       [not found]             ` <4D3E3546.80806-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
@ 2011-01-25 15:30               ` Dirk Brandewie
  0 siblings, 0 replies; 23+ messages in thread
From: Dirk Brandewie @ 2011-01-25 15:30 UTC (permalink / raw)
  To: Shinya Kuribayashi
  Cc: Jean-Hugues Deschenes, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg

On 01/24/2011 06:28 PM, Shinya Kuribayashi wrote:
> On 1/18/2011 2:19 AM, Jean-Hugues Deschenes wrote:
>>> +u32 dw_readl(struct dw_i2c_dev *dev, int offset)
>>> +{
>>> +	u32 value = readl(dev->base + offset);
>>> +
>>> +	if (dev->swab)
>>> +		return swab32(value);
>>> +	else
>>> +		return value;
>>> +}
>>> +EXPORT_SYMBOL(dw_readl);
>>> +
>>> +void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
>>> +{
>>> +	if (dev->swab)
>>> +		b = swab32(b);
>>> +
>>> +	writel(b, dev->base + offset);
>>> +}
>>> +EXPORT_SYMBOL(dw_writel);
>>
>> I would just suggest to declare these accessors as static and avoid to
>> export the symbols, especially given their short names. Inlining these
>> short, frequently-accessed functions is attractive.
>>
>>> +extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
>>> +extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
>>
>> Same here; I don't believe these lines are necessary.
>
> Ack.
>
> Furthermore, I'd like to see this patch at the start at Dirk-san's
> patchset.  We don't want to make a already proposed patch adapted to
> a modified driver.
ack

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2011-01-25 15:30 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-14 19:27 [PATCH RFC] Splitting i2c-designware.c to support PCI drivers dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
     [not found] ` <1295033256-30077-1-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-01-14 19:27   ` [PATCH 1/9] i2c-designware: Add designware PCI config option dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
2011-01-14 19:27   ` [PATCH 2/9] i2c-designware: Initial split of i2c-designware.c into core and bus specific parts dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
     [not found]     ` <1295033256-30077-3-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-01-25  1:58       ` Shinya Kuribayashi
     [not found]         ` <4D3E2E3F.1060506-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
2011-01-25 15:26           ` Dirk Brandewie
2011-01-14 19:27   ` [PATCH 3/9] i2c-designware: retrieve clock frequency based CONFIG_HAVE_CLK dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
2011-01-14 19:27   ` [PATCH 4/9] i2c-designware: Add support for Designware core behind PCI devices dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
2011-01-14 19:27   ` [PATCH 5/9] i2c-designware: move i2c functionality bit field to be adapter specific dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
     [not found]     ` <1295033256-30077-6-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-01-25  2:07       ` Shinya Kuribayashi
2011-01-14 19:27   ` [PATCH 6/9] i2c-designware: move controller config to bus specific portion of driver dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
     [not found]     ` <1295033256-30077-7-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-01-25  2:22       ` Shinya Kuribayashi
2011-01-14 19:27   ` [PATCH 7/9] i2c-designware: Allow mixed endianness accesses dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
     [not found]     ` <1295033256-30077-8-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-01-17 17:19       ` Jean-Hugues Deschenes
     [not found]         ` <2C61B7B7755780449CA3ED217819DA761BC7B3BD-VR+kULHyjlM/vpUtHNqADA@public.gmane.org>
2011-01-25  2:28           ` Shinya Kuribayashi
     [not found]             ` <4D3E3546.80806-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
2011-01-25 15:30               ` Dirk Brandewie
2011-01-25  2:45       ` Shinya Kuribayashi
2011-01-14 19:27   ` [PATCH 8/9] i2c-designware-pci: Add runtime power management support dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
     [not found]     ` <1295033256-30077-9-git-send-email-dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-01-25  3:00       ` Shinya Kuribayashi
2011-01-14 19:27   ` [PATCH 9/9] i2c-designware: Support multiple cores using same ISR dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w
2011-01-14 20:30   ` [PATCH RFC] Splitting i2c-designware.c to support PCI drivers Jean Delvare
     [not found]     ` <20110114213007.58c8b237-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org>
2011-01-14 21:48       ` Ben Dooks
     [not found]         ` <20110114214839.GC15795-SMNkleLxa3Z6Wcw2j4pizdi2O/JbrIOy@public.gmane.org>
2011-01-17 16:06           ` Dirk Brandewie
     [not found]             ` <4D346909.6030503-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-01-18 12:15               ` Jean Delvare

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.