Hi Matt,

Thanks for the tip! Attached is my port of the patch that is confirmed to be 
working on
MCF5271EVB eval board. The i2c clock speed seems a bit odd being hardcoded.
I'm not sure if where is the proper 'upstream' for this patch.

Is there a version of it that is being considered for 'mainstream' (i.e. 
kernel.org) inclusion?
I've seen at least 2 different patch in the /gpp adding and re-adding the same 
driver :)

Regards

- Richard Retanubun

<start of patch 1/2>

From c737008c63617fc68a2214fb5bb540f17240182c Mon Sep 17 00:00:00 2001
From: root <[email protected]>
Date: Tue, 17 Mar 2009 10:00:46 -0400
Subject: [PATCH] Initial commit of i2c-mcf driver for coldfire.
 Based on:

http://www.bitshrine.org/gpp/0006-I2C-device-driver.patch
http://www.bitshrine.org/gpp/0043-I2C-bug-fix.patch

With the m5301xsim.h part skipped and adapted to:
arch/m68k/include/asm/m527xsim.h

---
 arch/m68k/include/asm/m527xsim.h |   39 +++
 drivers/i2c/busses/Kconfig       |   10 +
 drivers/i2c/busses/Makefile      |    1 +
 drivers/i2c/busses/i2c-mcf.c     |  595 ++++++++++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-mcf.h     |   52 ++++
 5 files changed, 697 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-mcf.c
 create mode 100644 drivers/i2c/busses/i2c-mcf.h

diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h
index 1f63ab3..ce4df1b 100644
--- a/arch/m68k/include/asm/m527xsim.h
+++ b/arch/m68k/include/asm/m527xsim.h
@@ -70,5 +70,44 @@
 #define UART2_ENABLE_MASK      0x3f00
 #endif

+/*********************************************************************
+*
+* I2C Module (I2C) (Stolen from m5301xsim.h)
+*
+*********************************************************************/
+/* Register read/write macros */
+#ifdef CONFIG_M5271
+#define MCF_I2C_I2ADR           (volatile unsigned char *)(MCF_MBAR + 0x300)
+#define MCF_I2C_I2FDR           (volatile unsigned char *)(MCF_MBAR + 0x304)
+#define MCF_I2C_I2CR            (volatile unsigned char *)(MCF_MBAR + 0x308)
+#define MCF_I2C_I2SR            (volatile unsigned char *)(MCF_MBAR + 0x30C)
+#define MCF_I2C_I2DR            (volatile unsigned char *)(MCF_MBAR + 0x310)
+
+/* Bit definitions and macros for I2AR */
+#define MCF_I2C_I2AR_ADR(x)     (((x)&0x7F)<<1)
+
+/* Bit definitions and macros for I2FDR */
+#define MCF_I2C_I2FDR_IC(x)     (((x)&0x3F))
+
+/* Bit definitions and macros for I2CR */
+#define MCF_I2C_I2CR_RSTA       (0x04)
+#define MCF_I2C_I2CR_TXAK       (0x08)
+#define MCF_I2C_I2CR_MTX        (0x10)
+#define MCF_I2C_I2CR_MSTA       (0x20)
+#define MCF_I2C_I2CR_IIEN       (0x40)
+#define MCF_I2C_I2CR_IEN        (0x80)
+
+/* Bit definitions and macros for I2SR */
+#define MCF_I2C_I2SR_RXAK       (0x01)
+#define MCF_I2C_I2SR_IIF        (0x02)
+#define MCF_I2C_I2SR_SRW        (0x04)
+#define MCF_I2C_I2SR_IAL        (0x10)
+#define MCF_I2C_I2SR_IBB        (0x20)
+#define MCF_I2C_I2SR_IAAS       (0x40)
+#define MCF_I2C_I2SR_ICF        (0x80)
+
+/* Bit definitions and macros for I2DR */
+#define MCF_I2C_I2DR_DATA(x)    (x)
+#endif /* I2C Module for CONFIG_M5271 */
 /****************************************************************************/
 #endif /* m527xsim_h */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 7f95905..bdc410f 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -379,6 +379,16 @@ config I2C_IXP2000
          This driver is deprecated and will be dropped soon. Use i2c-gpio
          instead.

+config I2C_MCF
+       tristate "MCF ColdFire"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes to this option, support will be included for the
+         I2C on most ColdFire CPUs
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mcf.
+
 config I2C_MPC
        tristate "MPC107/824x/85xx/52xx/86xx"
        depends on PPC32
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 0c2c4b2..854e7ca 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
+obj-$(CONFIG_I2C_MCF)          += i2c-mcf.o

 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-mcf.c b/drivers/i2c/busses/i2c-mcf.c
new file mode 100644
index 0000000..f355b48
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mcf.c
@@ -0,0 +1,595 @@
+/*
+    i2c-mcf.c - Part of lm_sensors, Linux kernel modules for hardware 
monitoring
+
+    Copyright (c) 2005, Derek CL Cheung <[email protected]>
+                                       <http://www3.sympatico.ca/derek.cheung>
+
+    Copyright (c) 2006, emlix
+                       Sebastian Hess <[email protected]>
+
+    Yaroslav Vinogradov <[email protected]>
+    Copyright Freescale Semiconductor, Inc 2006-2007
+
+    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.
+
+    Changes:
+    v0.1       26 March 2005
+               Initial Release - developed on uClinux with 2.6.9 kernel
+
+    v0.2       29 May 2006
+               Modified to be more generic and added support for
+               i2c_master_xfer
+
+    v0.3       12 Sep 2007
+               Added support for more Coldfire systems, removed c++ comments
+
+    This I2C adaptor supports the ColdFire 5282 CPU I2C module. Since most 
Coldfire
+    CPUs' I2C module use the same register set (e.g., MCF5249), the code is 
very
+    portable and re-usable to other Coldfire CPUs.
+
+    The transmission frequency is set at about 100KHz for the 5282Lite CPU 
board with
+    8MHz crystal. If the CPU board uses different system clock frequency, you 
should
+    change the following line:
+                static int __init i2c_coldfire_init(void)
+                {
+                                .........
+                        // Set transmission frequency 0x15 = ~100kHz
+                        *MCF_I2C_I2FDR = 0x15;
+                                ........
+                }
+
+    Remember to perform a dummy read to set the ColdFire CPU's I2C module for 
read before
+    reading the actual byte from a device
+
+    The I2C_SM_BUS_BLOCK_DATA function are not yet ready but most lm_senors do 
not care
+
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/types.h>
+#include <linux/platform_device.h>
+#include "i2c-mcf.h"
+
+
+static struct i2c_algorithm coldfire_algorithm = {
+       .smbus_xfer     = coldfire_i2c_access,
+       .master_xfer    = coldfire_i2c_master,
+       .functionality  = coldfire_func,
+};
+
+
+static struct i2c_adapter coldfire_adapter = {
+       .owner          = THIS_MODULE,
+       .class          = I2C_CLASS_HWMON,
+       .algo           = &coldfire_algorithm,
+       .name           = "ColdFire I2C adapter",
+};
+
+
+__u16 lastaddr;
+__u16 lastop;
+
+static inline int coldfire_do_first_start(__u16 addr,__u16 flags)
+{
+       int err;
+       /*
+        * Generate a stop and put the I2C module into slave mode
+        */
+       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;
+
+       /*
+        * Generate a new Start signal
+        */
+       err = coldfire_i2c_start(flags & I2C_M_RD ? I2C_SMBUS_READ : 
I2C_SMBUS_WRITE,
+                               addr, FIRST_START);
+       if(err) return err;
+
+       lastaddr = addr;
+       lastop = flags & I2C_M_RD;  /* Ensure everything for new start */
+       return 0;
+}
+
+
+/*
+ *  read one byte data from the I2C bus
+ */
+static int coldfire_read_data(u8 * const rxData, const enum I2C_ACK_TYPE 
ackType) {
+
+       int timeout;
+
+       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;         /* master receive mode */
+
+       if (ackType == NACK)
+               *MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;     /* generate NA */
+       else
+               *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;    /* generate ACK */
+
+
+       /* read data from the I2C bus */
+       *rxData = *MCF_I2C_I2DR;
+
+       /* printk(">>> %s I2DR data is %.2x \n", __FUNCTION__, *rxData); */
+
+       /* wait for data transfer to complete */
+       timeout = 500;
+       while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IIF))
+               udelay(1);
+       if (timeout <= 0)
+               printk("%s - I2C IIF never set. Timeout is %d \n", 
__FUNCTION__, timeout);
+
+
+       /* reset the interrupt bit */
+       *MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;
+
+       if (timeout <= 0 )
+               return -1;
+       else
+               return 0;
+
+};
+
+
+/*
+ *  write one byte data onto the I2C bus
+ */
+static int coldfire_write_data(const u8 txData) {
+
+       int timeout;
+
+       timeout = 500;
+
+       *MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX;      /* I2C module into TX mode */
+       *MCF_I2C_I2DR = txData;                 /* send the data */
+
+       /* wait for data transfer to complete */
+       /* rely on the interrupt handling bit */
+       timeout = 500;
+       while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IIF))
+               udelay(1);
+       if (timeout <=0)
+               printk("%s - I2C IIF never set. Timeout is %d \n", 
__FUNCTION__, timeout);
+
+
+       /* reset the interrupt bit */
+       *MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;
+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
+       if (timeout <= 0 || (*MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK))
+#else
+       if (timeout <= 0 )
+#endif
+               return -1;
+       else
+               return 0;
+
+};
+
+
+
+
+/*
+ *  Generate I2C start or repeat start signal
+ *  Combine the 7 bit target_address and the R/W bit and put it onto the I2C 
bus
+ */
+static int coldfire_i2c_start(const char read_write, const u16 target_address, 
const enum I2C_START_TYPE start_type) {
+
+       int timeout;
+
+       /* printk(">>> %s START TYPE %s \n", __FUNCTION__, start_type == FIRST_START ? 
"FIRST_START" : "REPEAT_START"); */
+
+       *MCF_I2C_I2CR |= MCF_I2C_I2CR_IEN;
+
+       if (start_type == FIRST_START) {
+               /* Make sure the I2C bus is idle */
+               timeout = 500;          /* 500us timeout */
+               while (timeout-- && (*MCF_I2C_I2SR & MCF_I2C_I2SR_IBB))
+                       udelay(1);
+               if (timeout <= 0) {
+                       printk("%s - I2C bus always busy in the past 500us timeout 
is %d \n", __FUNCTION__, timeout);
+                       goto check_rc;
+               }
+               /* generate a START and put the I2C module into MASTER TX mode*/
+               *MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);
+
+               /* wait for bus busy to be set */
+               timeout = 500;
+               while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IBB))
+                       udelay(1);
+               if (timeout <= 0) {
+                       printk("%s - I2C bus is never busy after START. Timeout is 
%d \n", __FUNCTION__, timeout);
+                       goto check_rc;
+               }
+
+       } else {
+               /* this is repeat START */
+               udelay(500);    /* need some delay before repeat start */
+               *MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_RSTA);
+       }
+
+
+       /* combine the R/W bit and the 7 bit target address and put it onto the 
I2C bus */
+       *MCF_I2C_I2DR = ((target_address & 0x7F) << 1) | (read_write == 
I2C_SMBUS_WRITE ? 0x00 : 0x01);
+
+       /* wait for bus transfer to complete */
+       /* when one byte transfer is completed, IIF set at the faling edge of 
the 9th clock */
+       timeout = 500;
+       while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IIF))
+               udelay(1);
+       if (timeout <= 0)
+               printk("%s - I2C IIF never set. Timeout is %d \n", 
__FUNCTION__, timeout);
+
+
+check_rc:
+       /* reset the interrupt bit */
+       *MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;
+
+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
+       if (timeout <= 0 || (*MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK))
+#else
+       if (timeout <= 0)
+#endif
+               return -1;
+       else
+               return 0;
+};
+
+
+/*
+ *  5282 SMBUS supporting functions
+ */
+
+static s32 coldfire_i2c_access(struct i2c_adapter *adap, u16 addr,
+                             unsigned short flags, char read_write,
+                             u8 command, int size, union i2c_smbus_data *data)
+{
+       int i, len, rc = 0;
+       u8 rxData, tempRxData[2];
+
+       switch (size) {
+               case I2C_SMBUS_QUICK:
+                       rc = coldfire_i2c_start(read_write, addr, FIRST_START); 
        /* generate START */
+                        break;
+               case I2C_SMBUS_BYTE:
+                       rc = coldfire_i2c_start(read_write, addr, FIRST_START);
+                       *MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;             /* 
generate NA */
+                       if (read_write == I2C_SMBUS_WRITE)
+                               rc += coldfire_write_data(command);
+                       else {
+                               coldfire_read_data(&rxData, NACK);          /* 
dummy read */
+                               rc += coldfire_read_data(&rxData, NACK);
+                               data->byte = rxData;
+                       }
+                       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK; /* reset ACK bit */
+                       break;
+               case I2C_SMBUS_BYTE_DATA:
+                       rc = coldfire_i2c_start(I2C_SMBUS_WRITE, addr, 
FIRST_START);
+                       rc += coldfire_write_data(command);
+                       if (read_write == I2C_SMBUS_WRITE)
+                               rc += coldfire_write_data(data->byte);
+                       else {
+                               /* This is SMBus READ Byte Data Request. 
Perform REPEAT START */
+                               rc += coldfire_i2c_start(I2C_SMBUS_READ, addr, 
REPEAT_START);
+                               coldfire_read_data(&rxData, ACK);               
 /* dummy read */
+                               /* Disable Acknowledge, generate STOP after 
next byte transfer */
+                               rc += coldfire_read_data(&rxData, NACK);
+                               data->byte = rxData;
+                       }
+                       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;                /* 
reset to normal ACk */
+                       break;
+               case I2C_SMBUS_PROC_CALL:
+               case I2C_SMBUS_WORD_DATA:
+                       dev_info(&adap->dev, "size = I2C_SMBUS_WORD_DATA \n");
+                       rc = coldfire_i2c_start(I2C_SMBUS_WRITE, addr, 
FIRST_START);
+                       rc += coldfire_write_data(command);
+                       if (read_write == I2C_SMBUS_WRITE) {
+                               rc += coldfire_write_data(data->word & 0x00FF);
+                               rc += coldfire_write_data((data->word & 0x00FF) 
>> 8);
+                       } else {
+                               /* This is SMBUS READ WORD request. Peform 
REPEAT START */
+                               rc += coldfire_i2c_start(I2C_SMBUS_READ, addr, 
REPEAT_START);
+                               coldfire_read_data(&rxData, ACK);        /* 
dummy read */
+                               /* Disable Acknowledge, generate STOP after 
next byte transfer */
+                               /* read the MS byte from the device */
+                               rc += coldfire_read_data(&rxData, NACK);
+                               tempRxData[1] = rxData;
+                               /* read the LS byte from the device */
+                               rc += coldfire_read_data(&rxData, NACK);
+                               tempRxData[0] = rxData;
+                               /* the host driver expect little endian 
convention. Swap the byte */
+                               data->word = (tempRxData[0] << 8) | 
tempRxData[1];
+                       }
+                       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;
+                       break;
+               case I2C_SMBUS_BLOCK_DATA:
+                       /* this is not ready yet!!! */
+                       break;
+               case I2C_SMBUS_BLOCK_PROC_CALL:
+               {
+                       rc = coldfire_i2c_start(I2C_SMBUS_WRITE, addr, 
FIRST_START);
+                       rc += coldfire_write_data(command);
+                       if (read_write == I2C_SMBUS_READ) {
+                               /* This is SMBUS READ BLOCK request. Peform 
REPEAT START */
+                               rc += coldfire_i2c_start(I2C_SMBUS_READ, addr, 
REPEAT_START);
+                               coldfire_read_data(&rxData, ACK);        /* 
dummy read */
+                               len = data->block[0];
+                               if (len < 0) len = 0;
+                               if (len > 32) len = 32;
+                               for (i = 1; i < len; i++) {
+                                       /* read byte from the device */
+                                       rc += 
coldfire_read_data(&data->block[i], ACK);
+                               }
+                               /* read last byte from the device */
+                               rc += coldfire_read_data(&data->block[i], NACK);
+                       }
+                       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;
+                       break;
+               }
+               default:
+                       printk("Unsupported I2C size \n");
+                       rc = -1;
+                       break;
+       };
+
+       /* Generate a STOP and put I2C module into slave mode */
+       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;
+
+       /* restore interrupt */
+       *MCF_I2C_I2CR |= MCF_I2C_I2CR_IIEN;
+
+       if (rc < 0)
+               return -1;
+       else
+               return 0;
+};
+
+
+/*
+ *  List the SMBUS functions supported by this I2C adaptor
+ *  Also tell the I2C Subsystem that we are able of master_xfer()
+ */
+static u32 coldfire_func(struct i2c_adapter *adapter)
+{
+       return(I2C_FUNC_SMBUS_QUICK |
+              I2C_FUNC_SMBUS_BYTE |
+              I2C_FUNC_SMBUS_PROC_CALL |
+              I2C_FUNC_SMBUS_BYTE_DATA |
+              I2C_FUNC_SMBUS_WORD_DATA |
+              I2C_FUNC_I2C |
+              I2C_FUNC_SMBUS_BLOCK_DATA);
+};
+
+static int coldfire_i2c_master(struct i2c_adapter *adap,struct i2c_msg *msgs,
+                              int num)
+{
+       u8 dummyRead;
+       struct i2c_msg *p;
+       int i, err = 0;
+       int ic=0;
+
+       lastaddr = 0;
+       lastop = 8;
+
+       /* disable the IRQ, we are doing polling */
+       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_IIEN;
+
+       dev_dbg(&adap->dev,"Num of actions: %d\n", num);
+
+       for (i = 0; !err && i < num; i++) {
+               p = &msgs[i];
+
+
+               if (!p->len)
+               {
+                       dev_dbg(&adap->dev,"p->len == 0!\n");
+                       continue;
+               }
+               /*
+                * Generate a new Start, if the target address differs from the 
last target,
+                * generate a stop in this case first
+                */
+               if(p->addr != lastaddr)
+               {
+                       err = coldfire_do_first_start(p->addr,p->flags);
+                       if(err)
+                       {
+                               dev_dbg(&adap->dev,"First Init failed!\n");
+                               break;
+                       }
+               }
+
+               else if((p->flags & I2C_M_RD)  != lastop)
+               {
+                       /*
+                        * If the Operational Mode changed, we need to do this 
here ...
+                        */
+                       dev_dbg(&adap->dev,"%s(): Direction changed, was: %d; is 
now: %d\n",
+                               __FUNCTION__,lastop,p->flags & I2C_M_RD);
+
+                       /* Last op was an read, now it's write: complete stop 
and reinit */
+                       if (lastop & I2C_M_RD)
+                       {
+                               dev_dbg(&adap->dev,"%s(): The device is in read 
state, we must reset!\n",
+                                       __FUNCTION__);
+                               if((err = 
coldfire_do_first_start(p->addr,p->flags)))
+                                       break;
+                       }
+                       else
+                       {
+                               dev_dbg(&adap->dev,"%s(): We switchted to read 
mode\n",__FUNCTION__);
+                               if((err = coldfire_i2c_start((p->flags & 
I2C_M_RD) ? I2C_SMBUS_READ : I2C_SMBUS_WRITE,
+                                         p->addr, REPEAT_START)))
+                                       break;
+                       }
+
+                       lastop = p->flags & I2C_M_RD;    /* Save the last op */
+               }
+
+               if (p->flags & I2C_M_RD)
+               {
+                       /*
+                        * When ever we get here, a new session was activated, 
so
+                        * read a dummy byte
+                        */
+                       coldfire_read_data(&dummyRead, ACK);
+                       /*
+                        * read p->len -1 bytes with ACK to the slave,
+                        * read the last byte without the ACK, to inform him 
about the
+                        * stop afterwards
+                        */
+                       ic = 0;
+                       while(!err && (ic < p->len-1 ))
+                       {
+                               err = coldfire_read_data(p->buf+ic, ACK );
+                               ic++;
+                       }
+                       if(!err)
+                               err = coldfire_read_data(p->buf+ic, NACK);
+                       dev_dbg(&coldfire_adapter.dev,"read: %2x\n", 
p->buf[ic]);
+               }
+               else
+               {
+                       if(p->len == 2)
+                               dev_dbg(&coldfire_adapter.dev,"writing: 0x %2x 
%2x\n", p->buf[0], p->buf[1]);
+
+                       /*
+                        * Write data to the slave
+                        */
+                       for(ic=0; !err && ic < p->len; ic++)
+                       {
+                               err = coldfire_write_data(p->buf[ic]);
+                               if(err)
+                               {
+                                       dev_dbg(&coldfire_adapter.dev,"Failed to 
write data\n");
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Put the device into slave mode to enable the STOP Generation (the 
RTC needs this)
+        */
+       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;
+
+       *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;        /* reset the ACK bit */
+
+       /* restore interrupt */
+       *MCF_I2C_I2CR |= MCF_I2C_I2CR_IIEN;
+
+       /* Return the number of messages processed, or the error code. */
+       if (err == 0)
+               err = num;
+       return err;
+}
+
+
+/*
+ *  Initalize the 5282 I2C module
+ *  Disable the 5282 I2C interrupt capability. Just use callback
+ */
+
+static int __init i2c_coldfire_init(void)
+{
+       int retval;
+       u8  dummyRead;
+
+#if defined(CONFIG_M532x) || defined(CONFIG_M523x) || defined(CONFIG_M537x)
+       /*
+        * Initialize the GPIOs for I2C
+        */
+       MCF_GPIO_PAR_FECI2C |= (0
+                           | MCF_GPIO_PAR_FECI2C_PAR_SDA(3)
+                           | MCF_GPIO_PAR_FECI2C_PAR_SCL(3));
+#elif defined(CONFIG_M5253)
+       {
+       volatile u32 *reg;
+       /* GPIO Bit 41 = SCL0, Bit 42 = SDA0 */
+       reg = (volatile u32 *)(MCF_MBAR2 + MCFSIM2_GPIO1FUNC);
+       *reg &= 0xFFFFF9FF;
+       }
+#elif defined(CONFIG_M5227x)
+       /* Initialize the GPIOs for I2C */
+       MCF_GPIO_PAR_I2C |= (0
+                        | MCF_GPIO_PAR_I2C_PAR_SDA_SDA
+                        | MCF_GPIO_PAR_I2C_PAR_SCL_SCL);
+#elif defined(CONFIG_M5301x)
+       MCF_GPIO_PAR_FECI2C |= (0
+                           | MCF_GPIO_PAR_FECI2C_PAR_SDA_SDA
+                           | MCF_GPIO_PAR_FECI2C_PAR_SCL_SCL);
+#else
+       /* Initialize PASP0 and PASP1 to I2C functions, 5282 user guide 26-19 */
+       /* Port AS Pin Assignment Register (PASPAR)             */
+       /*              PASPA1 = 11 = AS1 pin is I2C SDA        */
+       /*              PASPA0 = 11 = AS0 pin is I2C SCL        */
+       *MCF5282_GPIO_PASPAR |= 0x000F;         /* u16 declaration */
+#endif
+
+
+       /* Set transmission frequency 0x15 = ~100kHz */
+       *MCF_I2C_I2FDR = 0x15;
+
+       /* set the 5282 I2C slave address though we never use it */
+       *MCF_I2C_I2ADR = 0x6A;
+
+       /* Enable I2C module and if IBB is set, do the special initialzation */
+       /* procedures as are documented at the 5282 User Guide page 24-11 */
+       *MCF_I2C_I2CR |= MCF_I2C_I2CR_IEN;
+       if ((*MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) == 1) {
+               printk("%s - do special 5282 I2C init procedures \n", 
__FUNCTION__);
+               *MCF_I2C_I2CR = 0x00;
+               *MCF_I2C_I2CR = 0xA0;
+               dummyRead = *MCF_I2C_I2DR;
+               *MCF_I2C_I2SR = 0x00;
+               *MCF_I2C_I2CR = 0x00;
+       }
+
+       /* default I2C mode is - slave and receive */
+       *MCF_I2C_I2CR &= ~(MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);
+
+       coldfire_adapter.dev.parent = &platform_bus;
+       retval = i2c_add_adapter(&coldfire_adapter);
+
+       if (retval < 0)
+               printk("%s - return code is: %d \n", __FUNCTION__, retval);
+
+       return retval;
+};
+
+
+/*
+ *  I2C module exit function
+ */
+
+static void __exit i2c_coldfire_exit(void)
+{
+       /* disable I2C and Interrupt */
+       *MCF_I2C_I2CR &= ~(MCF_I2C_I2CR_IEN | MCF_I2C_I2CR_IIEN);
+       i2c_del_adapter(&coldfire_adapter);
+
+};
+
+
+MODULE_AUTHOR("Derek CL Cheung <[email protected]>");
+MODULE_DESCRIPTION("MCF5282 I2C adaptor");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_coldfire_init);
+module_exit(i2c_coldfire_exit);
diff --git a/drivers/i2c/busses/i2c-mcf.h b/drivers/i2c/busses/i2c-mcf.h
new file mode 100644
index 0000000..5714e7d
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mcf.h
@@ -0,0 +1,52 @@
+/*
+    i2c-mcf5282.h - header file for i2c-mcf5282.c
+
+    Copyright (c) 2005, Derek CL Cheung <[email protected]>
+                                        <http://www3.sympatico.ca/derek.cheung>
+
+    Copyright (c) 2006, emlix and Freescale
+                       Sebastian Hess <[email protected]>
+                       Yaroslav Vinogradov <[email protected]>
+
+    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.
+
+    Changes:
+    v0.1       26 March 2005
+               Initial Release - developed on uClinux with 2.6.9 kernel
+    v0.2       29 May 2006
+               Modified to be more generic and added support for
+               i2c_master_xfer
+*/
+
+
+#ifndef __I2C_MCF5282_H__
+#define __I2C_MCF5282_H__
+
+enum I2C_START_TYPE { FIRST_START, REPEAT_START };
+enum I2C_ACK_TYPE { ACK, NACK};
+
+/* Function prototypes */
+static u32 coldfire_func(struct i2c_adapter *adapter);
+static s32 coldfire_i2c_access(struct i2c_adapter *adap, u16 address,
+                              unsigned short flags, char read_write,
+                              u8 command, int size, union i2c_smbus_data 
*data);
+static int coldfire_write_data(const u8 data);
+static int coldfire_i2c_start(const char read_write, const u16 target_address, 
const enum I2C_START_TYPE i2c_start);
+static int coldfire_read_data(u8 * const rxData, const enum I2C_ACK_TYPE 
ackType);
+static int coldfire_i2c_master(struct i2c_adapter *adap,struct i2c_msg *msgs, 
int num);
+void dumpReg(char *, u16 addr, u8 data);
+
+/********************************************************************/
+#endif /*  __I2C_MCF5282_H__ */
--
1.5.6.5

<start of patch 2/2>

From af7231dc5a6464ed4c77bd6d0239da1ed40fa5bd Mon Sep 17 00:00:00 2001
From: root <[email protected]>
Date: Tue, 17 Mar 2009 16:06:13 -0400
Subject: [PATCH] Fixups for i2c-mcf for MCF5271:

Added GPIO defines to turn on the I2C controller.
The speed and slave address will still have to be changed
per-platform (or made into a kernel config).

Signed-off-by: root <[email protected]>
---
 arch/m68k/include/asm/m527xsim.h |    7 +++++++
 drivers/i2c/busses/i2c-mcf.c     |   12 +++++++++---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h
index ce4df1b..04e644b 100644
--- a/arch/m68k/include/asm/m527xsim.h
+++ b/arch/m68k/include/asm/m527xsim.h
@@ -108,6 +108,13 @@

 /* Bit definitions and macros for I2DR */
 #define MCF_I2C_I2DR_DATA(x)    (x)
+
+/* Register to activate the GPIO pins dedicated for I2C controller */
+#define MCF_I2C_GPIO_PAR_FECI2C (volatile unsigned char *)(MCF_MBAR + 0x100047)
+/* Bit definitions for I2C GPIO pins */
+#define MCF_I2C_GPIO_PAR_FEC12C_SCL (0x0C)
+#define MCF_I2C_GPIO_PAR_FEC12C_SDA (0x03)
+
 #endif /* I2C Module for CONFIG_M5271 */
 /****************************************************************************/
 #endif /* m527xsim_h */
diff --git a/drivers/i2c/busses/i2c-mcf.c b/drivers/i2c/busses/i2c-mcf.c
index f355b48..f689ad5 100644
--- a/drivers/i2c/busses/i2c-mcf.c
+++ b/drivers/i2c/busses/i2c-mcf.c
@@ -80,7 +80,7 @@ static struct i2c_algorithm coldfire_algorithm = {

 static struct i2c_adapter coldfire_adapter = {
        .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON,
+       .class          = (I2C_CLASS_HWMON | I2C_CLASS_SPD),
        .algo           = &coldfire_algorithm,
        .name           = "ColdFire I2C adapter",
 };
@@ -297,7 +297,7 @@ static s32 coldfire_i2c_access(struct i2c_adapter *adap, 
u16 addr,
                        break;
                case I2C_SMBUS_PROC_CALL:
                case I2C_SMBUS_WORD_DATA:
-                       dev_info(&adap->dev, "size = I2C_SMBUS_WORD_DATA \n");
+                       dev_dbg(&adap->dev, "size = I2C_SMBUS_WORD_DATA \n");
                        rc = coldfire_i2c_start(I2C_SMBUS_WRITE, addr, 
FIRST_START);
                        rc += coldfire_write_data(command);
                        if (read_write == I2C_SMBUS_WRITE) {
@@ -534,12 +534,18 @@ static int __init i2c_coldfire_init(void)
        MCF_GPIO_PAR_FECI2C |= (0
                            | MCF_GPIO_PAR_FECI2C_PAR_SDA_SDA
                            | MCF_GPIO_PAR_FECI2C_PAR_SCL_SCL);
-#else
+#elif defined(CONFIG_M528x)
        /* Initialize PASP0 and PASP1 to I2C functions, 5282 user guide 26-19 */
        /* Port AS Pin Assignment Register (PASPAR)             */
        /*              PASPA1 = 11 = AS1 pin is I2C SDA        */
        /*              PASPA0 = 11 = AS0 pin is I2C SCL        */
        *MCF5282_GPIO_PASPAR |= 0x000F;         /* u16 declaration */
+#elif defined(CONFIG_M5271)
+       *MCF_I2C_GPIO_PAR_FECI2C |= (0
+                                | MCF_I2C_GPIO_PAR_FEC12C_SDA
+                                | MCF_I2C_GPIO_PAR_FEC12C_SCL);
+#else
+       #error "I2C controller pins not defined for this CPU type yet"
 #endif


--
1.5.6.5



_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to