8xx: port i2c-algo_8xx to 2.6

Based on Tom Rini's work

compile tested

Signed-off-by: Aristeu Sergio Rozanski Filho <aris at cathedrallabs.org>

Index: 2.6-8xx/drivers/i2c/algos/i2c-algo-8xx.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2.6-8xx/drivers/i2c/algos/i2c-algo-8xx.c    2005-08-05 17:16:08.000000000 
-0300
@@ -0,0 +1,625 @@
+/*
+ * i2c-algo-8xx.c i2x driver algorithms for MPC8XX CPM
+ * Copyright (c) 1999 Dan Malek (dmalek at jlc.net).
+ *
+    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.
+ *
+ * moved into proper i2c interface; separated out platform specific
+ * parts into i2c-rpx.c
+ * Brad Parker (brad at heeltoe.com)
+ */
+
+// XXX todo
+// timeout sleep?
+
+/* $Id: i2c-algo-8xx.c,v 1.7 2002/08/03 22:48:18 ac9410 Exp $ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-8xx.h>
+
+#define CPM_MAX_READ   513
+/* Try uncomment this if you have an older CPU(earlier than rev D4) */
+/* #define I2C_CHIP_ERRATA */
+
+static char *module_name = "i2c_algo_8xx";
+#define DEBUGP(level, x, y...) do { \
+                               if (cpm_debug >= level) \
+                                       printk(KERN_DEBUG "%s: " x, \
+                                              module_name, ## y); \
+                               } while(0)
+
+static wait_queue_head_t iic_wait;
+static ushort r_tbase, r_rbase;
+
+int cpm_scan = 0;
+int cpm_debug = 0;
+
+static  void
+cpm_iic_interrupt(void *dev_id, struct pt_regs *regs)
+ {
+       volatile i2c8xx_t *i2c = (i2c8xx_t *)dev_id;
+
+       DEBUGP(2, "cpm_iic_interrupt(dev_id=%p)\n", dev_id);
+
+#ifdef I2C_CHIP_ERRATA
+       /* Chip errata, clear enable.
+        * This seems to not be needed on rev D4 or newer CPUs.
+        * Someone with an older CPU needs to verify this.
+        */
+       i2c->i2c_i2mod &= ~1;
+#endif
+
+       /* Clear interrupt.
+       */
+       i2c->i2c_i2cer = 0xff;
+
+       /* Get 'me going again.
+       */
+       wake_up_interruptible(&iic_wait);
+}
+
+static void
+cpm_iic_init(struct i2c_algo_8xx_data *cpm_adap)
+{
+       volatile iic_t          *iip = cpm_adap->iip;
+       volatile i2c8xx_t       *i2c = cpm_adap->i2c;
+       unsigned char brg;
+       bd_t *bd = (bd_t *)__res;
+
+       DEBUGP(1, "cpm_iic_init() - iip=%p\n", iip);
+
+       /* Initialize the parameter ram.
+        * We need to make sure many things are initialized to zero,
+        * especially in the case of a microcode patch.
+        */
+       iip->iic_rstate = 0;
+       iip->iic_rdp = 0;
+       iip->iic_rbptr = 0;
+       iip->iic_rbc = 0;
+       iip->iic_rxtmp = 0;
+       iip->iic_tstate = 0;
+       iip->iic_tdp = 0;
+       iip->iic_tbptr = 0;
+       iip->iic_tbc = 0;
+       iip->iic_txtmp = 0;
+
+       /* Set up the IIC parameters in the parameter ram.
+       */
+       iip->iic_tbase = r_tbase = cpm_adap->dp_addr;
+       iip->iic_rbase = r_rbase = cpm_adap->dp_addr + sizeof(cbd_t) * 2;
+
+       iip->iic_tfcr = SMC_EB;
+       iip->iic_rfcr = SMC_EB;
+
+       /* Set maximum receive size.
+       */
+       iip->iic_mrblr = CPM_MAX_READ;
+
+       /* Initialize Tx/Rx parameters.
+       */
+       if (cpm_adap->reloc == 0) {
+               volatile cpm8xx_t *cp = cpm_adap->cp;
+
+               cp->cp_cpcr =
+                       mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+               while (cp->cp_cpcr & CPM_CR_FLG);
+       } else {
+               iip->iic_rbptr = iip->iic_rbase;
+               iip->iic_tbptr = iip->iic_tbase;
+               iip->iic_rstate = 0;
+               iip->iic_tstate = 0;
+       }
+
+       /* Select an arbitrary address.  Just make sure it is unique.
+       */
+       i2c->i2c_i2add = 0xfe;
+
+       /* Make clock run at 60 KHz.
+       */
+       brg = (unsigned char) (bd->bi_intfreq/(32*2*60000) -3);
+       i2c->i2c_i2brg = brg;
+
+       i2c->i2c_i2mod = 0x00;
+       i2c->i2c_i2com = 0x01; /* Master mode */
+
+       /* Disable interrupts.
+       */
+       i2c->i2c_i2cmr = 0;
+       i2c->i2c_i2cer = 0xff;
+
+       init_waitqueue_head(&iic_wait);
+
+       /* Install interrupt handler.
+       */
+       DEBUGP(1, "Install ISR for IRQ %d\n", CPMVEC_I2C);
+       cpm_install_handler(CPMVEC_I2C, cpm_iic_interrupt, (void *)i2c);
+}
+
+
+static int
+cpm_iic_shutdown(struct i2c_algo_8xx_data *cpm_adap)
+{
+       volatile i2c8xx_t *i2c = cpm_adap->i2c;
+
+       /* Shut down IIC.
+       */
+       i2c->i2c_i2mod &= ~1;
+       i2c->i2c_i2cmr = 0;
+       i2c->i2c_i2cer = 0xff;
+
+       return 0;
+}
+
+static void
+cpm_reset_iic_params(volatile iic_t *iip)
+{
+       iip->iic_tbase = r_tbase;
+       iip->iic_rbase = r_rbase;
+
+       iip->iic_tfcr = SMC_EB;
+       iip->iic_rfcr = SMC_EB;
+
+       iip->iic_mrblr = CPM_MAX_READ;
+
+       iip->iic_rstate = 0;
+       iip->iic_rdp = 0;
+       iip->iic_rbptr = iip->iic_rbase;
+       iip->iic_rbc = 0;
+       iip->iic_rxtmp = 0;
+       iip->iic_tstate = 0;
+       iip->iic_tdp = 0;
+       iip->iic_tbptr = iip->iic_tbase;
+       iip->iic_tbc = 0;
+       iip->iic_txtmp = 0;
+}
+
+#define BD_SC_NAK              ((ushort)0x0004) /* NAK - did not respond */
+#define BD_SC_OV               ((ushort)0x0002) /* OV - receive overrun */
+#define CPM_CR_CLOSE_RXBD      ((ushort)0x0007)
+
+static void force_close(struct i2c_algo_8xx_data *cpm)
+{
+       volatile i2c8xx_t *i2c = cpm->i2c;
+       if (cpm->reloc == 0) { /* micro code disabled */
+               volatile cpm8xx_t *cp = cpm->cp;
+
+               DEBUGP(1, "force_close()\n");
+               cp->cp_cpcr =
+                       mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_CLOSE_RXBD) |
+                       CPM_CR_FLG;
+
+               while (cp->cp_cpcr & CPM_CR_FLG);
+       }
+       i2c->i2c_i2cmr = 0x00;  /* Disable all interrupts */
+       i2c->i2c_i2cer = 0xff;
+}
+
+
+/* Read from IIC...
+ * abyte = address byte, with r/w flag already set
+ */
+static int
+cpm_iic_read(struct i2c_algo_8xx_data *cpm, u_char abyte, char *buf, int count)
+{
+       volatile iic_t *iip = cpm->iip;
+       volatile i2c8xx_t *i2c = cpm->i2c;
+       volatile cpm8xx_t *cp = cpm->cp;
+       volatile cbd_t  *tbdf, *rbdf;
+       u_char *tb;
+       unsigned long flags, tmo;
+
+       if (count >= CPM_MAX_READ)
+               return -EINVAL;
+
+       /* check for and use a microcode relocation patch */
+       if (cpm->reloc)
+               cpm_reset_iic_params(iip);
+
+       tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];
+       rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase];
+
+       /* To read, we need an empty buffer of the proper length.
+        * All that is used is the first byte for address, the remainder
+        * is just used for timing (and doesn't really have to exist).
+        */
+       tb = cpm->temp;
+       tb = (u_char *)(((uint)tb + 15) & ~15);
+       tb[0] = abyte;          /* Device address byte w/rw flag */
+
+       flush_dcache_range((unsigned long) tb, (unsigned long) (tb + 1));
+
+       DEBUGP(1, "cpm_iic_read(abyte=0x%x)\n", abyte);
+
+       tbdf->cbd_bufaddr = __pa(tb);
+       tbdf->cbd_datlen = count + 1;
+       tbdf->cbd_sc =
+               BD_SC_READY | BD_SC_LAST |
+               BD_SC_WRAP | BD_IIC_START;
+
+       iip->iic_mrblr = count + 1; /* prevent excessive read, +1
+                                     is needed otherwise will the
+                                     RXB interrupt come too early */
+
+       /* flush will invalidate too. */
+       flush_dcache_range((unsigned long) buf, (unsigned long) (buf+count));
+
+       rbdf->cbd_datlen = 0;
+       rbdf->cbd_bufaddr = __pa(buf);
+
+       rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP| BD_SC_INTRPT;
+       if(count > 16){
+               /* Chip bug, set enable here */
+               local_irq_save(flags);
+               i2c->i2c_i2cmr = 0x13;  /* Enable some interupts */
+               i2c->i2c_i2cer = 0xff;
+               i2c->i2c_i2mod |= 1;    /* Enable */
+               i2c->i2c_i2com |= 0x80; /* Begin transmission */
+
+               /* Wait for IIC transfer */
+               tmo = interruptible_sleep_on_timeout(&iic_wait,1*HZ);
+               local_irq_restore(flags);
+       } else { /* busy wait for small transfers, its faster */
+               i2c->i2c_i2cmr = 0x00;  /* Disable I2C interupts */
+               i2c->i2c_i2cer = 0xff;
+               i2c->i2c_i2mod |= 1;    /* Enable */
+               i2c->i2c_i2com |= 0x80; /* Begin transmission */
+               tmo = jiffies + 1*HZ;
+               /* Busy wait, with a timeout */
+               while(!(i2c->i2c_i2cer & 0x11 || time_after(jiffies, tmo)));
+       }
+
+       if (signal_pending(current) || !tmo){
+               force_close(cpm);
+               DEBUGP(1, "IIC read: timeout!\n");
+               return -EIO;
+       }
+#ifdef I2C_CHIP_ERRATA
+       /* Chip errata, clear enable. This is not needed on rev D4 CPUs.
+        Disabling I2C too early may cause too short stop condition */
+       udelay(4);
+       i2c->i2c_i2mod &= ~1;
+#endif
+
+       DEBUGP(1, "tx sc %04x, rx sc %04x\n", tbdf->cbd_sc, rbdf->cbd_sc);
+
+       if (tbdf->cbd_sc & BD_SC_READY) {
+               printk(KERN_INFO "IIC read; complete but tbuf ready\n");
+               force_close(cpm);
+               printk(KERN_INFO "tx sc %04x, rx sc %04x\n",
+                      tbdf->cbd_sc, rbdf->cbd_sc);
+       }
+
+       if (tbdf->cbd_sc & BD_SC_NAK) {
+               DEBUGP(1, "IIC read; no ack\n");
+               return -EREMOTEIO;
+       }
+
+       if (rbdf->cbd_sc & BD_SC_EMPTY) {
+               /* force_close(cpm); */
+               DEBUGP(1, "IIC read; complete but rbuf empty\n");
+               DEBUGP(1, "tx sc %04x, rx sc %04x\n", tbdf->cbd_sc, 
rbdf->cbd_sc);
+               return -EREMOTEIO;
+       }
+
+       if (rbdf->cbd_sc & BD_SC_OV) {
+               DEBUGP(1, "IIC read; Overrun\n");
+               return -EREMOTEIO;;
+       }
+
+       DEBUGP(1, "read %d bytes\n", rbdf->cbd_datlen);
+
+       if (rbdf->cbd_datlen < count) {
+               DEBUGP(1, "IIC read; short, wanted %d got %d\n", count,
+                      rbdf->cbd_datlen);
+               return 0;
+       }
+
+       return count;
+}
+
+/* Write to IIC...
+ * addr = address byte, with r/w flag already set
+ */
+static int
+cpm_iic_write(struct i2c_algo_8xx_data *cpm, u_char abyte, char *buf,int count)
+{
+       volatile iic_t *iip = cpm->iip;
+       volatile i2c8xx_t *i2c = cpm->i2c;
+       volatile cpm8xx_t *cp = cpm->cp;
+       volatile cbd_t  *tbdf;
+       u_char *tb;
+       unsigned long flags, tmo;
+
+       /* check for and use a microcode relocation patch */
+       if (cpm->reloc)
+               cpm_reset_iic_params(iip);
+       tb = cpm->temp;
+       tb = (u_char *)(((uint)tb + 15) & ~15);
+       *tb = abyte;            /* Device address byte w/rw flag */
+
+       flush_dcache_range((unsigned long) tb, (unsigned long) (tb+1));
+       flush_dcache_range((unsigned long) buf, (unsigned long) (buf+count));
+
+       DEBUGP(1, "cpm_iic_write(abyte=0x%x)\n", abyte);
+
+       /* set up 2 descriptors */
+       tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];
+
+       tbdf[0].cbd_bufaddr = __pa(tb);
+       tbdf[0].cbd_datlen = 1;
+       tbdf[0].cbd_sc = BD_SC_READY | BD_IIC_START;
+
+       tbdf[1].cbd_bufaddr = __pa(buf);
+       tbdf[1].cbd_datlen = count;
+       tbdf[1].cbd_sc = BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST | BD_SC_WRAP;
+
+       if (count > 16) {
+               /* Chip bug, set enable here */
+               local_irq_save(flags);
+               i2c->i2c_i2cmr = 0x13;  /* Enable some interupts */
+               i2c->i2c_i2cer = 0xff;
+               i2c->i2c_i2mod |= 1;    /* Enable */
+               i2c->i2c_i2com |= 0x80; /* Begin transmission */
+
+               /* Wait for IIC transfer */
+               tmo = interruptible_sleep_on_timeout(&iic_wait,1*HZ);
+               local_irq_restore(flags);
+       } else {  /* busy wait for small transfers, its faster */
+               i2c->i2c_i2cmr = 0x00;  /* Disable I2C interupts */
+               i2c->i2c_i2cer = 0xff;
+               i2c->i2c_i2mod |= 1;    /* Enable */
+               i2c->i2c_i2com |= 0x80; /* Begin transmission */
+               tmo = jiffies + 1*HZ;
+               /* Busy wait, with a timeout */
+               while(!(i2c->i2c_i2cer & 0x12 || time_after(jiffies, tmo)));
+       }
+
+       if (signal_pending(current) || !tmo){
+               force_close(cpm);
+               if (!tmo)
+                       DEBUGP(1, "IIC write: timeout!\n");
+               return -EIO;
+       }
+
+#if I2C_CHIP_ERRATA
+       /* Chip errata, clear enable. This is not needed on rev D4 CPUs.
+        Disabling I2C too early may cause too short stop condition */
+       udelay(4);
+       i2c->i2c_i2mod &= ~1;
+#endif
+       DEBUGP(1, "tx0 sc %04x, tx1 sc %04x\n", tbdf[0].cbd_sc,
+              tbdf[1].cbd_sc);
+
+       if ((tbdf[0].cbd_sc | tbdf[1].cbd_sc) & BD_SC_NAK) {
+               DEBUGP(1, "IIC write; no ack\n");
+               return 0;
+       }
+
+       if ((tbdf[0].cbd_sc | tbdf[1].cbd_sc) & BD_SC_READY) {
+               DEBUGP(1, "IIC write; complete but tbuf ready\n");
+               return 0;
+       }
+
+       return count;
+}
+
+/* See if an IIC address exists..
+ * addr = 7 bit address, unshifted
+ */
+static int
+cpm_iic_tryaddress(struct i2c_algo_8xx_data *cpm, int addr)
+{
+       volatile iic_t *iip = cpm->iip;
+       volatile i2c8xx_t *i2c = cpm->i2c;
+       volatile cpm8xx_t *cp = cpm->cp;
+       volatile cbd_t *tbdf, *rbdf;
+       u_char *tb;
+       unsigned long flags, len, tmo;
+
+       DEBUGP(2, "cpm_iic_tryaddress(cpm=%p,addr=%d)\n", cpm, addr);
+
+       /* check for and use a microcode relocation patch */
+       if (cpm->reloc)
+               cpm_reset_iic_params(iip);
+
+       if (addr == 0) {
+               DEBUGP(1, "iip %p, dp_addr 0x%x\n", cpm->iip, cpm->dp_addr);
+               DEBUGP(1, "iic_tbase %d, r_tbase %d\n", iip->iic_tbase,
+                      r_tbase);
+       }
+
+       tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];
+       rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase];
+
+       tb = cpm->temp;
+       tb = (u_char *)(((uint)tb + 15) & ~15);
+
+       /* do a simple read */
+       tb[0] = (addr << 1) | 1;        /* device address (+ read) */
+       len = 2;
+
+       flush_dcache_range((unsigned long) tb, (unsigned long) (tb+1));
+
+       tbdf->cbd_bufaddr = __pa(tb);
+       tbdf->cbd_datlen = len;
+       tbdf->cbd_sc =
+               BD_SC_READY | BD_SC_LAST |
+               BD_SC_WRAP | BD_IIC_START;
+
+       rbdf->cbd_datlen = 0;
+       rbdf->cbd_bufaddr = __pa(tb+2);
+       rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT;
+
+       local_irq_save(flags);
+       i2c->i2c_i2cmr = 0x13;  /* Enable some interupts */
+       i2c->i2c_i2cer = 0xff;
+       i2c->i2c_i2mod |= 1;    /* Enable */
+       i2c->i2c_i2com |= 0x80; /* Begin transmission */
+
+       DEBUGP(1, "about to sleep\n");
+
+       /* wait for IIC transfer */
+       tmo = interruptible_sleep_on_timeout(&iic_wait,1*HZ);
+       local_irq_restore(flags);
+
+#ifdef I2C_CHIP_ERRATA
+       /* Chip errata, clear enable. This is not needed on rev D4 CPUs.
+        Disabling I2C too early may cause too short stop condition */
+       udelay(4);
+       i2c->i2c_i2mod &= ~1;
+#endif
+
+       if (signal_pending(current) || !tmo){
+               force_close(cpm);
+               if (!tmo)
+                       DEBUGP(1, "IIC tryaddress: timeout!\n");
+               return -EIO;
+       }
+
+       DEBUGP(2, "back from sleep\n");
+
+       if (tbdf->cbd_sc & BD_SC_NAK) {
+               DEBUGP(2, "IIC try; no ack\n");
+               return 0;
+       }
+
+       if (tbdf->cbd_sc & BD_SC_READY)
+               printk(KERN_INFO "IIC try; complete but tbuf ready\n");
+
+       return 1;
+}
+
+static int cpm_xfer(struct i2c_adapter *i2c_adap,
+                   struct i2c_msg msgs[],
+                   int num)
+{
+       struct i2c_algo_8xx_data *adap = i2c_adap->algo_data;
+       struct i2c_msg *pmsg;
+       int i, ret;
+       u_char addr;
+
+       for (i = 0; i < num; i++) {
+               pmsg = &msgs[i];
+
+               DEBUGP(1, "#%d addr=0x%x flags=0x%x len=%d\n buf=%p\n",
+                      i, pmsg->addr, pmsg->flags, pmsg->len, pmsg->buf);
+
+               addr = pmsg->addr << 1;
+               if (pmsg->flags & I2C_M_RD)
+                       addr |= 1;
+               if (pmsg->flags & I2C_M_REV_DIR_ADDR)
+                       addr ^= 1;
+
+               if (pmsg->flags & I2C_M_RD) {
+                       /* read bytes into buffer*/
+                       ret = cpm_iic_read(adap, addr, pmsg->buf, pmsg->len);
+                       DEBUGP(1, "read %d bytes\n", ret);
+                       if (ret < pmsg->len)
+                               return (ret < 0)? ret:-EREMOTEIO;
+               } else {
+                       /* write bytes from buffer */
+                       ret = cpm_iic_write(adap, addr, pmsg->buf, pmsg->len);
+                       DEBUGP(1, "wrote %d\n", ret);
+                       if (ret < pmsg->len)
+                               return (ret < 0)? ret:-EREMOTEIO;
+               }
+       }
+       return num;
+}
+
+static u32 cpm_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
+              I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+static struct i2c_algorithm i2c_algo_8xx = {
+       .name = "MPC8xx CPM algorithm",
+       .id = I2C_ALGO_MPC8XX,
+       .master_xfer = cpm_xfer,
+       .functionality = cpm_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_8xx_add_bus(struct i2c_adapter *adap)
+{
+       int i;
+       struct i2c_algo_8xx_data *cpm_adap = adap->algo_data;
+
+       DEBUGP(1, "hw routines for %s registered.\n", adap->name);
+
+       /* register new adapter to i2c module... */
+
+       adap->id |= i2c_algo_8xx.id;
+       adap->algo = &i2c_algo_8xx;
+
+       i2c_add_adapter(adap);
+       cpm_iic_init(cpm_adap);
+
+       /* scan bus */
+       if (cpm_scan) {
+               printk(KERN_INFO "%s: scanning bus %s...\n", module_name,
+                      adap->name);
+               for (i = 0; i < 128; i++)
+                       if (cpm_iic_tryaddress(cpm_adap, i)) {
+                               printk("(%02x)", i << 1);
+                       }
+               printk("\n");
+       }
+       return 0;
+}
+
+int i2c_8xx_del_bus(struct i2c_adapter *adap)
+{
+       int res;
+       struct i2c_algo_8xx_data *cpm_adap = adap->algo_data;
+
+       cpm_iic_shutdown(cpm_adap);
+
+       if ((res = i2c_del_adapter(adap)) < 0)
+               return res;
+
+       printk(KERN_INFO "%s: adapter unregistered: %s\n", module_name,
+              adap->name);
+
+       return 0;
+}
+
+module_param(cpm_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(cpm_debug, "Sets the debug level. (0 = none, 1 = normal, "
+                ">1 = plenty");
+MODULE_AUTHOR("Brad Parker <brad at heeltoe.com>");
+MODULE_DESCRIPTION("I2C-Bus MPC8XX algorithm");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(i2c_8xx_add_bus);
+EXPORT_SYMBOL(i2c_8xx_del_bus);
+
Index: 2.6-8xx/drivers/i2c/algos/Makefile
===================================================================
--- 2.6-8xx.orig/drivers/i2c/algos/Makefile     2005-07-28 12:05:11.000000000 
-0300
+++ 2.6-8xx/drivers/i2c/algos/Makefile  2005-08-05 16:48:26.000000000 -0300
@@ -8,6 +8,7 @@
 obj-$(CONFIG_I2C_ALGOITE)      += i2c-algo-ite.o
 obj-$(CONFIG_I2C_ALGO_SIBYTE)  += i2c-algo-sibyte.o
 obj-$(CONFIG_I2C_ALGO_SGI)     += i2c-algo-sgi.o
+obj-$(CONFIG_I2C_ALGO8XX)      += i2c-algo-8xx.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
 EXTRA_CFLAGS += -DDEBUG
Index: 2.6-8xx/include/linux/i2c-algo-8xx.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2.6-8xx/include/linux/i2c-algo-8xx.h        2005-08-05 16:57:21.000000000 
-0300
@@ -0,0 +1,28 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-algo-8xx.h i2c driver algorithms for MPX8XX CPM                      */
+/* ------------------------------------------------------------------------- */
+
+/* $Id$ */
+
+#ifndef I2C_ALGO_8XX_H
+#define I2C_ALGO_8XX_H
+
+#include <linux/i2c.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+
+struct i2c_algo_8xx_data {
+       uint dp_addr;
+       int reloc;
+       volatile i2c8xx_t *i2c;
+       volatile iic_t  *iip;
+       volatile cpm8xx_t *cp;
+
+       u_char  temp[513];
+};
+
+int i2c_8xx_add_bus(struct i2c_adapter *);
+int i2c_8xx_del_bus(struct i2c_adapter *);
+
+#endif /* I2C_ALGO_8XX_H */
+

Reply via email to