From: ebs@ebshome.net (Eugene Surovegin)
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
Date: Thu, 19 May 2005 06:25:02 +0000 [thread overview]
Message-ID: <20040622185116.GA4146@gate.ebshome.net> (raw)
Skipped content of type multipart/mixed-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.lm-sensors.org/pipermail/lm-sensors/attachments/20040622/2b1ff55b/attachment.bin
WARNING: multiple messages have this Message-ID (diff)
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);
next reply other threads:[~2005-05-19 6:25 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-06-22 18:51 Eugene Surovegin [this message]
2005-05-19 6:25 ` [PATCH] PPC4xx IIC driver: 0-length transactions bit-banging Eugene Surovegin
2004-07-08 23:07 ` [PATCH] PPC4xx IIC driver: 0-length transactions bit-banging implementation Greg KH
2005-05-19 6:25 ` [PATCH] PPC4xx IIC driver: 0-length transactions bit-banging 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 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.