linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Eugene Surovegin <ebs@ebshome.net>
To: Greg Kroah-Hartman <greg@kroah.com>
Cc: sensors@Stimpy.netroedge.com, linuxppc-embedded@lists.linuxppc.org
Subject: [PATCH] PPC4xx IIC driver: 0-length transactions bit-banging implementation
Date: Tue, 22 Jun 2004 11:51:16 -0700	[thread overview]
Message-ID: <20040622185116.GA4146@gate.ebshome.net> (raw)

[-- Attachment #1: Type: text/plain, Size: 273 bytes --]

Greg,

IBM PPC 4xx i2c controller doesn't support 0-length transactions (e.g.
used by SMBUS_QUICK). This patch implements bit-banging emulation for
such requests and removes temporary kludge added earlier.

Signed-off-by: Eugene Surovegin <ebs@ebshome.net>

Please, apply.

[-- Attachment #2: ibm_iic_smbus_quick-2.6-2.diff --]
[-- Type: text/plain, Size: 4276 bytes --]

===== drivers/i2c/busses/i2c-ibm_iic.c 1.9 vs edited =====
--- 1.9/drivers/i2c/busses/i2c-ibm_iic.c	Mon May 17 12:29:23 2004
+++ edited/drivers/i2c/busses/i2c-ibm_iic.c	Tue Jun 22 08:58:59 2004
@@ -45,7 +45,7 @@
=20
 #include "i2c-ibm_iic.h"
=20
-#define DRIVER_VERSION "2.01"
+#define DRIVER_VERSION "2.1"
=20
 MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
 MODULE_LICENSE("GPL");
@@ -96,6 +96,31 @@
 #  define DUMP_REGS(h,dev)	((void)0)
 #endif
=20
+/* Bus timings (in ns) for bit-banging */
+static struct i2c_timings {
+	unsigned int hd_sta;
+	unsigned int su_sto;
+	unsigned int low;
+	unsigned int high;
+	unsigned int buf;
+} timings [] = {
+/* Standard mode (100 KHz) */
+{
+	.hd_sta	= 4000,
+	.su_sto	= 4000,
+	.low	= 4700,
+	.high	= 4000,
+	.buf	= 4700,
+},
+/* Fast mode (400 KHz) */
+{
+	.hd_sta = 600,
+	.su_sto	= 600,
+	.low 	= 1300,
+	.high 	= 600,
+	.buf	= 1300,
+}};
+
 /* Enable/disable interrupt generation */
 static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable)
 {
@@ -196,6 +221,104 @@
 }

 /*
+ * Do 0-length transaction using bit-banging through IIC_DIRECTCNTL register.
+ */
+
+/* Wait for SCL and/or SDA to be high */
+static int iic_dc_wait(volatile struct iic_regs *iic, u8 mask)
+{
+	unsigned long x = jiffies + HZ / 28 + 2;
+	while ((in_8(&iic->directcntl) & mask) != mask){
+		if (unlikely(time_after(jiffies, x)))
+			return -1;
+		cond_resched();
+	}
+	return 0;
+}
+
+static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p)
+{
+	volatile struct iic_regs* iic = dev->vaddr;
+	const struct i2c_timings* t = &timings[dev->fast_mode ? 1 : 0];
+	u8 mask, v, sda;
+	int i, res;
+
+	/* Only 7-bit addresses are supported */
+	if (unlikely(p->flags & I2C_M_TEN)){
+		DBG("%d: smbus_quick - 10 bit addresses are not supported\n",
+			dev->idx);
+		return -EINVAL;
+	}
+
+	DBG("%d: smbus_quick(0x%02x)\n", dev->idx, p->addr);
+
+	/* Reset IIC interface */
+	out_8(&iic->xtcntlss, XTCNTLSS_SRST);
+
+	/* Wait for bus to become free */
+	out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
+	if (unlikely(iic_dc_wait(iic, DIRCNTL_MSDA | DIRCNTL_MSC)))
+		goto err;
+	ndelay(t->buf);
+
+	/* START */
+	out_8(&iic->directcntl, DIRCNTL_SCC);
+	sda = 0;
+	ndelay(t->hd_sta);
+
+	/* Send address */
+	v = (u8)((p->addr << 1) | ((p->flags & I2C_M_RD) ? 1 : 0));
+	for (i = 0, mask = 0x80; i < 8; ++i, mask >>= 1){
+		out_8(&iic->directcntl, sda);
+		ndelay(t->low / 2);
+		sda = (v & mask) ? DIRCNTL_SDAC : 0;
+		out_8(&iic->directcntl, sda);
+		ndelay(t->low / 2);
+
+		out_8(&iic->directcntl, DIRCNTL_SCC | sda);
+		if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC)))
+			goto err;
+		ndelay(t->high);
+	}
+
+	/* ACK */
+	out_8(&iic->directcntl, sda);
+	ndelay(t->low / 2);
+	out_8(&iic->directcntl, DIRCNTL_SDAC);
+	ndelay(t->low / 2);
+	out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
+	if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC)))
+		goto err;
+	res = (in_8(&iic->directcntl) & DIRCNTL_MSDA) ? -EREMOTEIO : 1;
+	ndelay(t->high);
+
+	/* STOP */
+	out_8(&iic->directcntl, 0);
+	ndelay(t->low);
+	out_8(&iic->directcntl, DIRCNTL_SCC);
+	if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC)))
+		goto err;
+	ndelay(t->su_sto);
+	out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
+
+	ndelay(t->buf);
+
+	DBG("%d: smbus_quick -> %s\n", dev->idx, res ? "NACK" : "ACK");
+out:
+	/* Remove reset */
+	out_8(&iic->xtcntlss, 0);
+
+	/* Reinitialize interface */
+	iic_dev_init(dev);
+
+	return res;
+err:
+	DBG("%d: smbus_quick - bus is stuck\n", dev->idx);
+	res = -EREMOTEIO;
+	goto out;
+}
+
+/*
  * IIC interrupt handler
  */
 static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs)
@@ -457,13 +580,10 @@
 		if (unlikely(msgs[i].len <= 0)){
 			if (num == 1 && !msgs[0].len){
 				/* Special case for I2C_SMBUS_QUICK emulation.
-				 * Although this logic is FAR FROM PERFECT, this
-				 * is what previous driver version did.
 				 * IBM IIC doesn't support 0-length transactions
-				 * (except bit-banging through IICx_DIRECTCNTL).
+				 * so we have to emulate them using bit-banging.
 				 */
-				DBG("%d: zero-length msg kludge\n", dev->idx);
-				return 0;
+				return iic_smbus_quick(dev, &msgs[0]);
 			}
 			DBG("%d: invalid len %d in msg[%d]\n", dev->idx,
 				msgs[i].len, i);

             reply	other threads:[~2004-06-22 18:51 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-22 18:51 Eugene Surovegin [this message]
2004-07-08 23:07 ` [PATCH] PPC4xx IIC driver: 0-length transactions bit-banging implementation Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040622185116.GA4146@gate.ebshome.net \
    --to=ebs@ebshome.net \
    --cc=greg@kroah.com \
    --cc=linuxppc-embedded@lists.linuxppc.org \
    --cc=sensors@Stimpy.netroedge.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).