Skip to contentSkip to conversation

[2.6] New PPC4xx I2C driver

PATCH New Matt Porter 3 participants 6 messages May 19, 2005 I2C

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 [2.6] New PPC4xx I2C driver

This updates the current 2.6 PPC 4xx driver to the rewritten version we have in the PPC development tree. It is cleaner, has less bugs, and has more features. Please apply.

-Matt

This BitKeeper patch contains the following changesets:
1.1316

# This is a BitKeeper patch. What follows are the unified diffs for the

# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	mporter
# Host:	kernel.crashing.org
# Root:	/home/mporter/src/i2c

#
#--- 1.5/drivers/i2c/i2c-algo-ibm_ocp.c Tue Mar 11 13:21:11 2003
#+++ 1.7/drivers/i2c/i2c-ibm_iic.c Fri Sep 12 12:31:23 2003
#@@ -1,900 +1,729 @@
# /*

#-   -------------------------------------------------------------------------
#-   i2c-algo-ibm_ocp.c i2c driver algorithms for IBM PPC 405 adapters	    
#-   -------------------------------------------------------------------------

#-
#- Ian DaSilva, MontaVista Software, Inc.
#- [email protected] or [email protected]
#-
#- Copyright 2000 MontaVista Software Inc.
#-
#- Changes made to support the IIC peripheral on the IBM PPC 405
#-
#-

#-   ---------------------------------------------------------------------------
#-   This file was highly leveraged from i2c-algo-pcf.c, which was created
#-   by Simon G. Vogl and Hans Berglund:

#-
#-
#- Copyright (C) 1995-1997 Simon G. Vogl
#- 1998-2000 Hans Berglund
#-

#-   With some changes from Ky?sti M?lkki <[email protected]> and 
#-   Frodo Looijaard <[email protected]> ,and also from Martin Bailey
#-   <[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.
#-   ---------------------------------------------------------------------------
#-
#-   History: 01/20/12 - Armin
#-   	[email protected]
#-   	ported up to 2.4.16+	
#-
#-   Version 02/03/25 - Armin
#-       converted to ocp format
#-       removed commented out or #if 0 code
#-       added G?rard Basler's fix to iic_combined_transaction() such that it 
#-       returns the number of successfully completed transfers .

#-*/
#-
#-
#-#include <linux/kernel.h>
#+ * drivers/i2c/i2c-ibm_iic.c
#+ *
#+ * Support for the IIC peripheral on IBM PPC 4xx
#+ *
#+ * Copyright (c) 2003 Zultys Technologies.
#+ * Eugene Surovegin <[email protected]> or <[email protected]> #+ *
#+ * Based on original work by
#+ * Ian DaSilva <[email protected]>
#+ * Armin Kuster <[email protected]>
#+ * Matt Porter <[email protected]>
#+ *
#+ * Copyright 2000-2003 MontaVista Software Inc.
#+ *
#+ * Original driver version was highly leveraged from i2c-elektor.c #+ *
#+ * Copyright 1995-97 Simon G. Vogl
#+ * 1998-99 Hans Berglund
#+ *
#+ * With some changes from Ky?sti M?lkki <[email protected]>
#+ * and even Frodo Looijaard <[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.
#+ *
#+ */
# #include <linux/module.h>
#+#include <linux/kernel.h>
#+#include <linux/ioport.h>
# #include <linux/delay.h>
# #include <linux/slab.h>
# #include <linux/init.h>
#-#include <linux/errno.h>
#-#include <linux/sched.h>
#+#include <linux/interrupt.h>
#+#include <asm/irq.h>
#+#include <asm/io.h>
# #include <linux/i2c.h>
#-#include <linux/i2c-algo-ibm_ocp.h>
#+#include <linux/i2c-id.h>
# #include <asm/ocp.h>
#+#include <asm/ibm4xx.h>
#
#+#include "i2c-ibm_iic.h"
#
#-/* ----- global defines ----------------------------------------------- */ #-#define DEB(x) if (i2c_debug>=1) x
#-#define DEB2(x) if (i2c_debug>=2) x
#-#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/ #-#define DEBPROTO(x) if (i2c_debug>=9) x;
#- /* debug the protocol by showing transferred bits */
#-#define DEF_TIMEOUT 5
#-
#-
#-/* ----- global variables --------------------------------------------- */
#+#define DRIVER_VERSION "2.0"
#
#+MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); #+MODULE_LICENSE("GPL");
#
#-/* module parameters:
#- */
#-static int i2c_debug=0;
#-
#-/* --- setting states on the bus with the right timing: --------------- */
#-
#-#define iic_outb(adap, reg, val) adap->setiic(adap->data, (int) &(reg), val) #-#define iic_inb(adap, reg) adap->getiic(adap->data, (int) &(reg)) #-
#-#define IICO_I2C_SDAHIGH 0x0780
#-#define IICO_I2C_SDALOW 0x0781
#-#define IICO_I2C_SCLHIGH 0x0782
#-#define IICO_I2C_SCLLOW 0x0783
#-#define IICO_I2C_LINEREAD 0x0784
#+static int iic_scan = 0;
#+MODULE_PARM(iic_scan, "i");
#+MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus"); #+
#+static int iic_force_poll = 0;
#+MODULE_PARM(iic_force_poll, "i"); #+MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
#+
#+static int iic_force_fast = 0;
#+MODULE_PARM(iic_force_fast, "i"); #+MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)");
#
#-#define IIC_SINGLE_XFER 0
#-#define IIC_COMBINED_XFER 1
#+#define DBG_LEVEL 0
#

#-#define IIC_ERR_LOST_ARB        -2
#-#define IIC_ERR_INCOMPLETE_XFR  -3
#-#define IIC_ERR_NACK            -1

#+#ifdef DBG
#+#undef DBG
#+#endif
#
#-/* --- other auxiliary functions -------------------------------------- */
#+#ifdef DBG2
#+#undef DBG2
#+#endif
#
#+#if DBG_LEVEL > 0
#+# define DBG(x...) printk(KERN_DEBUG "ibm-iic" ##x)
#+#else
#+# define DBG(x...) ((void)0)
#+#endif
#+#if DBG_LEVEL > 1
#+# define DBG2(x...) DBG( ##x )
#+#else
#+# define DBG2(x...) ((void)0)
#+#endif
#+#if DBG_LEVEL > 2
#+static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) #+{
#+ volatile struct iic_regs *iic = dev->vaddr;
#+ printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header);

#+	printk(KERN_DEBUG "  cntl     = 0x%02x, mdcntl = 0x%02x\n"
#+	       KERN_DEBUG "  sts      = 0x%02x, extsts = 0x%02x\n"
#+	       KERN_DEBUG "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
#+	       KERN_DEBUG "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",

#+ in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
#+ in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
#+ in_8(&iic->xtcntlss), in_8(&iic->directcntl));
#+}
#+# define DUMP_REGS(h,dev) dump_iic_regs((h),(dev))
#+#else
#+# define DUMP_REGS(h,dev) ((void)0)
#+#endif
#
#-//
#-// Description: Puts this process to sleep for a period equal to timeout #-//
#-static inline void iic_sleep(unsigned long timeout)
#+/* Enable/disable interrupt generation */
#+static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable) # {
#- schedule_timeout( timeout * HZ);
#+ out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0);
# }
#-
#-
#-//
#-// Description: This performs the IBM PPC 405 IIC initialization sequence #-// as described in the PPC405GP data book.
#-//
#-static int iic_init (struct i2c_algo_iic_data *adap)
#+
#+/*
#+ * Initialize IIC interface.
#+ */
#+static void iic_dev_init(struct ibm_iic_private* dev)
# {
#- struct iic_regs *iic;
#- struct iic_ibm *adap_priv_data = adap->data;
#- unsigned short retval;
#- iic = (struct iic_regs *) adap_priv_data->iic_base;
#-
#- /* Clear master low master address */
#- iic_outb(adap,iic->lmadr, 0);
#-
#- /* Clear high master address */
#- iic_outb(adap,iic->hmadr, 0);
#-
#- /* Clear low slave address */
#- iic_outb(adap,iic->lsadr, 0);
#-
#- /* Clear high slave address */
#- iic_outb(adap,iic->hsadr, 0);
#+ volatile struct iic_regs *iic = dev->vaddr;
#
#- /* Clear status */
#- iic_outb(adap,iic->sts, 0x0a);
#-
#- /* Clear extended status */
#- iic_outb(adap,iic->extsts, 0x8f);
#-
#- /* Set clock division */
#- iic_outb(adap,iic->clkdiv, 0x04);
#-
#- retval = iic_inb(adap, iic->clkdiv);
#- DEB(printk("iic_init: CLKDIV register = %x\n", retval));
#-
#- /* Enable interrupts on Requested Master Transfer Complete */
#- iic_outb(adap,iic->intmsk, 0x01);
#-
#- /* Clear transfer count */
#- iic_outb(adap,iic->xfrcnt, 0x0);
#-
#- /* Clear extended control and status */
#- iic_outb(adap,iic->xtcntlss, 0xf0);
#+ DBG("%d: init\n", dev->idx);
#+
#+ /* Clear master address */
#+ out_8(&iic->lmadr, 0);
#+ out_8(&iic->hmadr, 0);
#+
#+ /* Clear slave address */
#+ out_8(&iic->lsadr, 0);
#+ out_8(&iic->hsadr, 0);
#+
#+ /* Clear status & extended status */
#+ out_8(&iic->sts, STS_SCMP | STS_IRQA);
#+ out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | EXTSTS_LA
#+ | EXTSTS_ICT | EXTSTS_XFRA);
#+
#+ /* Set clock divider */
#+ out_8(&iic->clkdiv, dev->clckdiv);
#+
#+ /* Clear transfer count */
#+ out_8(&iic->xfrcnt, 0);
#+
#+ /* Clear extended control and status */
#+ out_8(&iic->xtcntlss, XTCNTLSS_SRC | XTCNTLSS_SRS | XTCNTLSS_SWC
#+ | XTCNTLSS_SWS);
#

#-        /* Set mode control (flush master data buf, enable hold SCL, exit */
#-        /* unknown state.                                                 */
#-        iic_outb(adap,iic->mdcntl, 0x47);

#+ /* Clear control register */
#+ out_8(&iic->cntl, 0);
#+
#+ /* Enable interrupts if possible */
#+ iic_interrupt_mode(dev, dev->irq >= 0);
#
#- /* Clear control register */
#- iic_outb(adap,iic->cntl, 0x0);
#+ /* Set mode control */
#+ out_8(&iic->mdcntl, MDCNTL_FMDB | MDCNTL_EINT | MDCNTL_EUBS
#+ | (dev->fast_mode ? MDCNTL_FSM : 0));
#
#- DEB2(printk(KERN_DEBUG "iic_init: Initialized IIC on PPC 405\n"));
#- return 0;
#+ DUMP_REGS("iic_init", dev);
# }
#
#-
#-//
#-// Description: After we issue a transaction on the IIC bus, this function #-// is called. It puts this process to sleep until we get an interrupt from #-// from the controller telling us that the transaction we requested in complete. #-//
#-static int wait_for_pin(struct i2c_algo_iic_data *adap, int *status) #+/*
#+ * Reset IIC interface
#+ */
#+static void iic_dev_reset(struct ibm_iic_private* dev)
# {
#+ volatile struct iic_regs *iic = dev->vaddr;
#+ int i;
#+ u8 dc;
#+
#+ DBG("%d: soft reset\n", dev->idx);
#+ DUMP_REGS("reset", dev);
#+
#+ /* Place chip in the reset state */
#+ out_8(&iic->xtcntlss, XTCNTLSS_SRST);
#+
#+ /* Check if bus is free */
#+ dc = in_8(&iic->directcntl);
#+ if (!DIRCTNL_FREE(dc)){
#+ DBG("%d: trying to regain bus control\n", dev->idx);
#+
#+ /* Try to set bus free state */
#+ out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
#+
#+ /* Wait until we regain bus control */
#+ for (i = 0; i < 100; ++i){
#+ dc = in_8(&iic->directcntl);
#+ if (DIRCTNL_FREE(dc))
#+ break;
#+
#+ /* Toggle SCL line */
#+ dc ^= DIRCNTL_SCC;
#+ out_8(&iic->directcntl, dc);
#+ udelay(10);
#+ dc ^= DIRCNTL_SCC;
#+ out_8(&iic->directcntl, dc);
#+
#+ /* be nice */
#+ cond_resched();
#+ }
#+ }
#+
#+ /* Remove reset */
#+ out_8(&iic->xtcntlss, 0);
#+
#+ /* Reinitialize interface */
#+ iic_dev_init(dev);
#+}
#
#- int timeout = DEF_TIMEOUT;
#- int retval;
#- struct iic_regs *iic;
#- struct iic_ibm *adap_priv_data = adap->data;
#- iic = (struct iic_regs *) adap_priv_data->iic_base;
#-
#-
#- *status = iic_inb(adap, iic->sts);
#-#ifndef STUB_I2C
#+/*
#+ * IIC interrupt handler
#+ */
#+static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs) #+{
#+ struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id;
#+ volatile struct iic_regs* iic = dev->vaddr;
#+
#+ DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n",
#+ dev->idx, in_8(&iic->sts), in_8(&iic->extsts));
#+
#+ /* Acknowledge IRQ and wakeup iic_wait_for_tc */
#+ out_8(&iic->sts, STS_IRQA | STS_SCMP);
#+ wake_up_interruptible(&dev->wq);
#+
#+ return IRQ_HANDLED;
#+}
#
#- while (timeout-- && (*status & 0x01)) {
#- adap->waitforpin(adap->data);
#- *status = iic_inb(adap, iic->sts);
#- }
#-#endif
#- if (timeout <= 0) {
#- /* Issue stop signal on the bus, and force an interrupt */

#-           retval = iic_inb(adap, iic->cntl);
#-           iic_outb(adap, iic->cntl, retval | 0x80);
#-           /* Clear status register */
#-	   iic_outb(adap, iic->sts, 0x0a);
#-	   /* Exit unknown bus state */
#-	   retval = iic_inb(adap, iic->mdcntl);
#-	   iic_outb(adap, iic->mdcntl, (retval | 0x02));
#-
#-	   // Check the status of the controller.  Does it still see a
#-	   // pending transfer, even though we've tried to stop any
#-	   // ongoing transaction?
#-           retval = iic_inb(adap, iic->sts);
#-           retval = retval & 0x01;
#-           if(retval) {
#-	      // The iic controller is hosed.  It is not responding to any
#-	      // of our commands.  We have already tried to force it into
#-	      // a known state, but it has not worked.  Our only choice now
#-	      // is a soft reset, which will clear all registers, and force
#-	      // us to re-initialize the controller.
#-	      /* Soft reset */
#-              iic_outb(adap, iic->xtcntlss, 0x01);
#-              udelay(500);
#-              iic_init(adap);
#-	      /* Is the pending transfer bit in the sts reg finally cleared? */
#-              retval = iic_inb(adap, iic->sts);
#-              retval = retval & 0x01;
#-              if(retval) {
#-                 printk(KERN_CRIT "The IIC Controller is hosed.  A processor reset is required\n");
#-              }
#-	      // For some reason, even though the interrupt bit in this
#-	      // register was set during iic_init, it didn't take.  We
#-	      // need to set it again.  Don't ask me why....this is just what
#-	      // I saw when testing timeouts.

#- iic_outb(adap, iic->intmsk, 0x01);
#- }
#- return(-1);
#+/*
#+ * Get master transfer result and clear errors if any.
#+ * Returns the number of actually transferred bytes or error (<0) #+ */
#+static int iic_xfer_result(struct ibm_iic_private* dev)
#+{
#+ volatile struct iic_regs *iic = dev->vaddr;
#+
#+ if (unlikely(in_8(&iic->sts) & STS_ERR)){
#+ DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx,
#+ in_8(&iic->extsts));
#+
#+ /* Clear errors and possible pending IRQs */
#+ out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD |
#+ EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA);
#+
#+ /* Flush master data buffer */
#+ out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
#+
#+ /* Is bus free?
#+ * If error happened during combined xfer
#+ * IIC interface is usually stuck in some strange
#+ * state, the only way out - soft reset.
#+ */
#+ if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
#+ DBG("%d: bus is stuck, resetting\n", dev->idx);
#+ iic_dev_reset(dev);
#+ }
#+ return -EREMOTEIO;
# }
# else
#- return(0);
#+ return in_8(&iic->xfrcnt) & XFRCNT_MTC_MASK;
# }
#
#+/*
#+ * Try to abort active transfer.
#+ */
#+static void iic_abort_xfer(struct ibm_iic_private* dev)
#+{
#+ volatile struct iic_regs *iic = dev->vaddr;
#+ unsigned long x;
#+
#+ DBG("%d: iic_abort_xfer\n", dev->idx);
#+
#+ out_8(&iic->cntl, CNTL_HMT);
#+
#+ /*
#+ * Wait for the abort command to complete.
#+ * It's not worth to be optimized, just poll (timeout >= 1 tick)
#+ */
#+ x = jiffies + 2;
#+ while ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
#+ if (time_after(jiffies, x)){
#+ DBG("%d: abort timeout, resetting...\n", dev->idx);
#+ iic_dev_reset(dev);
#+ return;
#+ }
#+ schedule();
#+ }
#
#-//------------------------------------
#-// Utility functions
#-//
#-
#-
#-//
#-// Description: Look at the status register to see if there was an error #-// in the requested transaction. If there is, look at the extended status #-// register and determine the exact cause.
#-//
#-int analyze_status(struct i2c_algo_iic_data *adap, int *error_code) #-{

#-   int ret;
#-   struct iic_regs *iic;
#-   struct iic_ibm *adap_priv_data = adap->data;
#-   iic = (struct iic_regs *) adap_priv_data->iic_base;

#-
#-
#- ret = iic_inb(adap, iic->sts);
#- if(ret & 0x04) {

#-      // Error occurred
#-      ret = iic_inb(adap, iic->extsts);
#-      if(ret & 0x04) {

#- // Lost arbitration
#- *error_code = IIC_ERR_LOST_ARB;
#- }
#- if(ret & 0x02) {
#- // Incomplete transfer
#- *error_code = IIC_ERR_INCOMPLETE_XFR;
#- }
#- if(ret & 0x01) {
#- // Master transfer aborted by a NACK during the transfer of the
#- // address byte
#- *error_code = IIC_ERR_NACK;
#- }
#- return -1;
#- }
#- return 0;
#+ /* Just to clear errors */
#+ iic_xfer_result(dev);
# }
#
#-
#-//
#-// Description: This function is called by the upper layers to do the #-// grunt work for a master send transaction
#-//
#-static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf,
#- int count, int xfer_flag)
#-{
#- struct iic_regs *iic;
#- struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
#- struct iic_ibm *adap_priv_data = adap->data;
#- int wrcount, status, timeout;
#- int loops, remainder, i, j;
#- int ret, error_code;
#- iic = (struct iic_regs *) adap_priv_data->iic_base;
#-
#-
#- if( count = 0 ) return 0;
#- wrcount = 0;
#- loops = count / 4;
#- remainder = count % 4;
#-
#- if((loops > 1) && (remainder = 0)) {
#- for(i=0; i<(loops-1); i++) {
#- //
#- // Write four bytes to master data buffer
#- //
#- for(j=0; j<4; j++) {
#- iic_outb(adap, iic->mdbuf,
#- buf[wrcount++]);
#- }

#-	      //
#-	      // Issue command to IICO device to begin transmission
#-	      //
#-	      iic_outb(adap, iic->cntl, 0x35);
#-	      //
#-	      // Wait for transmission to complete.  When it does, 
#-	      //loop to the top of the for statement and write the 
#-	      // next four bytes.
#-	      //
#-	      timeout = wait_for_pin(adap, &status);
#-	      if(timeout < 0) {
#-	         //
#-	         // Error handling
#-	         //
#-                 //printk(KERN_ERR "Error: write timeout\n");
#-                 return wrcount;
#-	      }
#-	      ret = analyze_status(adap, &error_code);
#-	      if(ret < 0) {
#-                 if(error_code = IIC_ERR_INCOMPLETE_XFR) {
#-                    // Return the number of bytes transferred
#-                    ret = iic_inb(adap, iic->xfrcnt);
#-                    ret = ret & 0x07;
#-                    return (wrcount-4+ret);

#- }
#- else return error_code;
#- }
#- }
#- }
#- else if((loops >= 1) && (remainder > 0)){
#- //printk(KERN_DEBUG "iic_sendbytes: (loops >= 1)\n");
#- for(i=0; i<loops; i++) {

#-              //
#-              // Write four bytes to master data buffer
#-              //
#-              for(j=0; j<4; j++) {
#-                 iic_outb(adap, iic->mdbuf,
#-                 buf[wrcount++]);
#-              }
#-              //
#-              // Issue command to IICO device to begin transmission
#-              //
#-              iic_outb(adap, iic->cntl, 0x35);
#-              //
#-              // Wait for transmission to complete.  When it does,
#-              //loop to the top of the for statement and write the
#-              // next four bytes.
#-              //
#-              timeout = wait_for_pin(adap, &status);
#-              if(timeout < 0) {
#-                 //
#-                 // Error handling
#-                 //
#-                 //printk(KERN_ERR "Error: write timeout\n");
#-                 return wrcount;
#-              }
#-              ret = analyze_status(adap, &error_code);
#-              if(ret < 0) {
#-                 if(error_code = IIC_ERR_INCOMPLETE_XFR) {
#-                    // Return the number of bytes transferred
#-                    ret = iic_inb(adap, iic->xfrcnt);
#-                    ret = ret & 0x07;
#-                    return (wrcount-4+ret);

#- }
#- else return error_code;
#- }
#- }
#- }
#-
#- //printk(KERN_DEBUG "iic_sendbytes: expedite write\n");
#- if(remainder = 0) remainder = 4;
#- // remainder = remainder - 1;
#- //
#- // Write the remaining bytes (less than or equal to 4)
#- //
#- for(i=0; i<remainder; i++) {
#- iic_outb(adap, iic->mdbuf, buf[wrcount++]);
#- //printk(KERN_DEBUG "iic_sendbytes: data transferred = %x, wrcount = %d\n", buf[wrcount-1], (wrcount-1));
#- }
#- //printk(KERN_DEBUG "iic_sendbytes: Issuing write\n");
#-
#- if(xfer_flag = IIC_COMBINED_XFER) {
#- iic_outb(adap, iic->cntl, (0x09 | ((remainder-1) << 4)));
#- }
#- else {
#- iic_outb(adap, iic->cntl, (0x01 | ((remainder-1) << 4)));
#- }
#- DEB2(printk(KERN_DEBUG "iic_sendbytes: Waiting for interrupt\n"));
#- timeout = wait_for_pin(adap, &status);
#- if(timeout < 0) {

#-       	   //
#-           // Error handling
#-           //
#-           //printk(KERN_ERR "Error: write timeout\n");
#-           return wrcount;
#-        }
#-        ret = analyze_status(adap, &error_code);
#-        if(ret < 0) {
#-           if(error_code = IIC_ERR_INCOMPLETE_XFR) {
#-              // Return the number of bytes transferred
#-              ret = iic_inb(adap, iic->xfrcnt);
#-              ret = ret & 0x07;
#-              return (wrcount-4+ret);

#- }
#- else return error_code;
#- }
#- DEB2(printk(KERN_DEBUG "iic_sendbytes: Got interrupt\n"));
#- return wrcount;
#-}
#-
#-
#-//
#-// Description: Called by the upper layers to do the grunt work for
#-// a master read transaction.
#-//
#-static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count, int xfer_type) #-{
#- struct iic_regs *iic;
#- int rdcount=0, i, status, timeout;
#- struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
#- struct iic_ibm *adap_priv_data = adap->data;
#- int loops, remainder, j;
#- int ret, error_code;
#- iic = (struct iic_regs *) adap_priv_data->iic_base;
#-
#- if(count = 0) return 0;
#- loops = count / 4;
#- remainder = count % 4;
#-
#- //printk(KERN_DEBUG "iic_readbytes: loops = %d, remainder = %d\n", loops, remainder);
#-
#- if((loops > 1) && (remainder = 0)) {
#- //printk(KERN_DEBUG "iic_readbytes: (loops > 1) && (remainder = 0)\n");
#- for(i=0; i<(loops-1); i++) {
#- //
#- // Issue command to begin master read (4 bytes maximum)
#- //

#-	      //printk(KERN_DEBUG "--->Issued read command\n");
#-	      iic_outb(adap, iic->cntl, 0x37);
#-	      //
#-              // Wait for transmission to complete.  When it does,
#-              // loop to the top of the for statement and write the
#-              // next four bytes.
#-              //

#- //printk(KERN_DEBUG "--->Waiting for interrupt\n");
#- timeout = wait_for_pin(adap, &status);
#- if(timeout < 0) {
#- // Error Handler
#- //printk(KERN_ERR "Error: read timed out\n");
#- return rdcount;
#- }
#- //printk(KERN_DEBUG "--->Got interrupt\n");
#-
#- ret = analyze_status(adap, &error_code);
#- if(ret < 0) {
#- if(error_code = IIC_ERR_INCOMPLETE_XFR)
#- return rdcount;
#- else
#- return error_code;
#- }
#-
#- for(j=0; j<4; j++) {
#- // Wait for data to shuffle to top of data buffer
#- // This value needs to optimized.
#- udelay(1);
#- buf[rdcount] = iic_inb(adap, iic->mdbuf);
#- rdcount++;
#- //printk(KERN_DEBUG "--->Read one byte\n");
#- }
#- }
#- }
#-
#- else if((loops >= 1) && (remainder > 0)){
#- //printk(KERN_DEBUG "iic_readbytes: (loops >=1) && (remainder > 0)\n");
#- for(i=0; i<loops; i++) {

#-              //
#-              // Issue command to begin master read (4 bytes maximum)
#-              //
#-              //printk(KERN_DEBUG "--->Issued read command\n");
#-              iic_outb(adap, iic->cntl, 0x37);
#-              //
#-              // Wait for transmission to complete.  When it does,
#-              // loop to the top of the for statement and write the
#-              // next four bytes.
#-              //
#-              //printk(KERN_DEBUG "--->Waiting for interrupt\n");
#-              timeout = wait_for_pin(adap, &status);
#-              if(timeout < 0) {
#-                 // Error Handler
#-                 //printk(KERN_ERR "Error: read timed out\n");
#-                 return rdcount;

#- }
#- //printk(KERN_DEBUG "--->Got interrupt\n");
#-
#- ret = analyze_status(adap, &error_code);
#- if(ret < 0) {
#- if(error_code = IIC_ERR_INCOMPLETE_XFR)
#- return rdcount;
#- else
#- return error_code;
#- }
#-
#- for(j=0; j<4; j++) {

#-                 // Wait for data to shuffle to top of data buffer
#-                 // This value needs to optimized.
#-                 udelay(1);
#-                 buf[rdcount] = iic_inb(adap, iic->mdbuf);
#-                 rdcount++;
#-                 //printk(KERN_DEBUG "--->Read one byte\n");

#- }
#- }
#- }
#-
#- //printk(KERN_DEBUG "iic_readbytes: expedite read\n");
#- if(remainder = 0) remainder = 4;
#- DEB2(printk(KERN_DEBUG "iic_readbytes: writing %x to IICO_CNTL\n", (0x03 | ((remainder-1) << 4))));
#-
#- if(xfer_type = IIC_COMBINED_XFER) {
#- iic_outb(adap, iic->cntl, (0x0b | ((remainder-1) << 4)));
#- }
#- else {
#- iic_outb(adap, iic->cntl, (0x03 | ((remainder-1) << 4)));
#- }
#- DEB2(printk(KERN_DEBUG "iic_readbytes: Wait for pin\n"));
#- timeout = wait_for_pin(adap, &status);
#- DEB2(printk(KERN_DEBUG "iic_readbytes: Got the interrupt\n"));
#- if(timeout < 0) {
#- // Error Handler
#- //printk(KERN_ERR "Error: read timed out\n");
#- return rdcount;
#- }
#-
#- ret = analyze_status(adap, &error_code);
#- if(ret < 0) {
#- if(error_code = IIC_ERR_INCOMPLETE_XFR)
#- return rdcount;
#- else
#- return error_code;
#- }
#-
#- //printk(KERN_DEBUG "iic_readbyte: Begin reading data buffer\n");
#- for(i=0; i<remainder; i++) {
#- buf[rdcount] = iic_inb(adap, iic->mdbuf);
#- // printk(KERN_DEBUG "iic_readbytes: Character read = %x\n", buf[rdcount]);
#- rdcount++;
#- }
#-
#- return rdcount;
#-}
#-
#-
#-//
#-// Description: This function implements combined transactions. Combined
#-// transactions consist of combinations of reading and writing blocks of data. #-// Each transfer (i.e. a read or a write) is separated by a repeated start
#-// condition.
#-//
#-static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) #-{

#-   int i;
#-   struct i2c_msg *pmsg;
#-   int ret;

#-
#- DEB2(printk(KERN_DEBUG "Beginning combined transaction\n"));
#- for(i=0; i < num; i++) {
#- pmsg = &msgs[i];
#- if(pmsg->flags & I2C_M_RD) {
#-
#- // Last read or write segment needs to be terminated with a stop
#- if(i < num-1) {
#- DEB2(printk(KERN_DEBUG "This one is a read\n"));
#- }
#- else {
#- DEB2(printk(KERN_DEBUG "Doing the last read\n"));
#- }
#- ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, (i < num-1) ? IIC_COMBINED_XFER : IIC_SINGLE_XFER);
#-
#- if (ret != pmsg->len) {
#- DEB2(printk("i2c-algo-ppc405.o: fail: "
#- "only read %d bytes.\n",ret));
#- return i;
#- }
#- else {
#- DEB2(printk("i2c-algo-ppc405.o: read %d bytes.\n",ret));
#- }
#+/*
#+ * Wait for master transfer to complete.
#+ * It puts current process to sleep until we get interrupt or timeout expires. #+ * Returns the number of transferred bytes or error (<0)
#+ */
#+static int iic_wait_for_tc(struct ibm_iic_private* dev){
#+
#+ volatile struct iic_regs *iic = dev->vaddr;
#+ int ret = 0;
#+
#+ if (dev->irq >= 0){
#+ /* Interrupt mode */
#+ wait_queue_t wait;
#+ init_waitqueue_entry(&wait, current);
#+
#+ add_wait_queue(&dev->wq, &wait);
#+ set_current_state(TASK_INTERRUPTIBLE);
#+ if (in_8(&iic->sts) & STS_PT)
#+ schedule_timeout(dev->adap.timeout * HZ);
#+ set_current_state(TASK_RUNNING);
#+ remove_wait_queue(&dev->wq, &wait);
#+
#+ if (unlikely(signal_pending(current))){
#+ DBG("%d: wait interrupted\n", dev->idx);
#+ ret = -ERESTARTSYS;
#+ } else if (unlikely(in_8(&iic->sts) & STS_PT)){
#+ DBG("%d: wait timeout\n", dev->idx);
#+ ret = -ETIMEDOUT;
# }
#- else if(!(pmsg->flags & I2C_M_RD)) {
#-
#- // Last read or write segment needs to be terminated with a stop
#- if(i < num-1) {
#- DEB2(printk(KERN_DEBUG "This one is a write\n"));
#- }
#- else {
#- DEB2(printk(KERN_DEBUG "Doing the last write\n"));
#- }
#- ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, (i < num-1) ? IIC_COMBINED_XFER : IIC_SINGLE_XFER);
#-
#- if (ret != pmsg->len) {
#- DEB2(printk("i2c-algo-ppc405.o: fail: "
#- "only wrote %d bytes.\n",ret));
#- return i;
#+ }
#+ else {
#+ /* Polling mode */
#+ unsigned long x = jiffies + dev->adap.timeout * HZ;
#+
#+ while (in_8(&iic->sts) & STS_PT){
#+ if (unlikely(time_after(jiffies, x))){
#+ DBG("%d: poll timeout\n", dev->idx);
#+ ret = -ETIMEDOUT;
#+ break;
# }
#- else {
#- DEB2(printk("i2c-algo-ppc405.o: wrote %d bytes.\n",ret));
#+
#+ if (unlikely(signal_pending(current))){
#+ DBG("%d: poll interrupted\n", dev->idx);
#+ ret = -ERESTARTSYS;
#+ break;
# }
#- }
#+ schedule();
#+ }
# }
#-
#- return num;
#+
#+ if (unlikely(ret < 0))
#+ iic_abort_xfer(dev);
#+ else
#+ ret = iic_xfer_result(dev);
#+
#+ DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret);
#+
#+ return ret;
# }
#
#-
#-//
#-// Description: Whenever we initiate a transaction, the first byte clocked #-// onto the bus after the start condition is the address (7 bit) of the #-// device we want to talk to. This function manipulates the address specified #-// so that it makes sense to the hardware when written to the IIC peripheral. #-//
#-// Note: 10 bit addresses are not supported in this driver, although they are #-// supported by the hardware. This functionality needs to be implemented. #-//
#-static inline int iic_doAddress(struct i2c_algo_iic_data *adap,
#- struct i2c_msg *msg, int retries)
#-{
#- struct iic_regs *iic;
#- unsigned short flags = msg->flags;
#- unsigned char addr;
#- struct iic_ibm *adap_priv_data = adap->data;
#- iic = (struct iic_regs *) adap_priv_data->iic_base;
#-
#-//
#-// The following segment for 10 bit addresses needs to be ported #-//
#-/* Ten bit addresses not supported right now
#- if ( (flags & I2C_M_TEN) ) {
#- // a ten bit address
#- addr = 0xf0 | (( msg->addr >> 7) & 0x03);
#- DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
#- // try extended address code...
#- ret = try_address(adap, addr, retries);
#- if (ret!=1) {
#- printk(KERN_ERR "iic_doAddress: died at extended address code.\n");
#- return -EREMOTEIO;
#- }
#- // the remaining 8 bit address
#- iic_outb(adap,msg->addr & 0x7f);
#- // Status check comes here
#- if (ret != 1) {
#- printk(KERN_ERR "iic_doAddress: died at 2nd address code.\n");
#- return -EREMOTEIO;
#- }
#- if ( flags & I2C_M_RD ) {
#- i2c_repstart(adap);
#- // okay, now switch into reading mode
#- addr |= 0x01;
#- ret = try_address(adap, addr, retries);
#- if (ret!=1) {
#- printk(KERN_ERR "iic_doAddress: died at extended address code.\n");
#- return -EREMOTEIO;
#- }
#+/*
#+ * Low level master transfer routine
#+ */
#+static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
#+ int combined_xfer)
#+{
#+ volatile struct iic_regs *iic = dev->vaddr;
#+ char* buf = pm->buf;
#+ int i, j, loops, ret = 0;
#+ int len = pm->len;
#+
#+ u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT;
#+ if (pm->flags & I2C_M_RD)
#+ cntl |= CNTL_RW;
#+
#+ loops = (len + 3) / 4;
#+ for (i = 0; i < loops; ++i, len -= 4){
#+ int count = len > 4 ? 4 : len;
#+ u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT);
#+
#+ if (!(cntl & CNTL_RW))
#+ for (j = 0; j < count; ++j)
#+ out_8((volatile u8*)&iic->mdbuf, *buf++);
#+
#+ if (i < loops - 1)
#+ cmd |= CNTL_CHT;
#+ else if (combined_xfer)
#+ cmd |= CNTL_RPST;
#+
#+ DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd);
#+
#+ /* Start transfer */
#+ out_8(&iic->cntl, cmd);
#+
#+ /* Wait for completion */
#+ ret = iic_wait_for_tc(dev);
#+
#+ if (unlikely(ret < 0))
#+ break;
#+ else if (unlikely(ret != count)){
#+ DBG("%d: xfer_bytes, requested %d, transfered %d\n",
#+ dev->idx, count, ret);
#+
#+ /* If it's not a last part of xfer, abort it */
#+ if (combined_xfer || (i < loops - 1))
#+ iic_abort_xfer(dev);
#+
#+ ret = -EREMOTEIO;
#+ break;
# }
#- } else ----------> // normal 7 bit address
#-
#-Ten bit addresses not supported yet */
#-
#- addr = ( msg->addr << 1 );
#- if (flags & I2C_M_RD )
#- addr |= 1;
#- if (flags & I2C_M_REV_DIR_ADDR )
#- addr ^= 1;
#- //
#- // Write to the low slave address
#- //
#- iic_outb(adap, iic->lmadr, addr);
#- //
#- // Write zero to the high slave register since we are
#- // only using 7 bit addresses
#- //
#- iic_outb(adap, iic->hmadr, 0);
#-
#- return 0;
#+
#+ if (cntl & CNTL_RW)
#+ for (j = 0; j < count; ++j)
#+ *buf++ = in_8((volatile u8*)&iic->mdbuf);
#+ }
#+
#+ return ret > 0 ? 0 : ret;
# }
#
#+/*
#+ * Set target slave address for master transfer
#+ */
#+static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) #+{
#+ volatile struct iic_regs *iic = dev->vaddr;
#+ u16 addr = msg->addr;
#+
#+ DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx,
#+ addr, msg->flags & I2C_M_TEN ? 10 : 7);
#+
#+ if (msg->flags & I2C_M_TEN){

#+	    out_8(&iic->cntl, CNTL_AMD);
#+	    out_8(&iic->lmadr, addr);
#+	    out_8(&iic->hmadr, 0xf0 | ((addr >> 7) & 0x06));

#+ }
#+ else {
#+ out_8(&iic->cntl, 0);
#+ out_8(&iic->lmadr, addr << 1);
#+ }
#+}
#
#-//
#-// Description: Prepares the controller for a transaction (clearing status #-// registers, data buffers, etc), and then calls either iic_readbytes or #-// iic_sendbytes to do the actual transaction.
#-//
#-static int iic_xfer(struct i2c_adapter *i2c_adap,
#- struct i2c_msg msgs[],
#- int num)
#-{
#- struct iic_regs *iic;
#- struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
#- struct iic_ibm *adap_priv_data = adap->data;
#- struct i2c_msg *pmsg;
#- int i = 0;
#- int ret;
#- iic = (struct iic_regs *) adap_priv_data->iic_base;
#-
#- pmsg = &msgs[i];
#-
#- //
#- // Clear status register
#- //
#- DEB2(printk(KERN_DEBUG "iic_xfer: iic_xfer: Clearing status register\n"));
#- iic_outb(adap, iic->sts, 0x0a);
#-
#- //
#- // Wait for any pending transfers to complete
#- //
#- DEB2(printk(KERN_DEBUG "iic_xfer: Waiting for any pending transfers to complete\n"));
#- while((ret = iic_inb(adap, iic->sts)) = 0x01) {
#- ;
#- }
#-
#- //
#- // Flush master data buf
#- //
#- DEB2(printk(KERN_DEBUG "iic_xfer: Clearing master data buffer\n"));
#- ret = iic_inb(adap, iic->mdcntl);
#- iic_outb(adap, iic->mdcntl, ret | 0x40);
#-
#- //
#- // Load slave address
#- //
#- DEB2(printk(KERN_DEBUG "iic_xfer: Loading slave address\n"));
#- ret = iic_doAddress(adap, pmsg, i2c_adap->retries);
#-

#-        //
#-        // Check to see if the bus is busy
#-        //
#-        ret = iic_inb(adap, iic->extsts);
#-        // Mask off the irrelevent bits
#-        ret = ret & 0x70;
#-        // When the bus is free, the BCS bits in the EXTSTS register are 0b100
#-        if(ret != 0x40) return IIC_ERR_LOST_ARB;

#-
#- //
#- // Combined transaction (read and write)
#- //
#- if(num > 1) {
#- DEB2(printk(KERN_DEBUG "iic_xfer: Call combined transaction\n"));
#- ret = iic_combined_transaction(i2c_adap, msgs, num);
#- }
#- //
#- // Read only
#- //
#- else if((num = 1) && (pmsg->flags & I2C_M_RD)) {

#-	   //
#-	   // Tell device to begin reading data from the  master data 
#-	   //
#-	   DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's read\n"));
#-	   ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);

#- }
#- //
#- // Write only
#- //
#- else if((num = 1 ) && (!(pmsg->flags & I2C_M_RD))) {

#-	   //
#-	   // Write data to master data buffers and tell our device
#-	   // to begin transmitting
#-	   //
#-	   DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's write\n"));
#-	   ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);

#- }
#-
#- return ret;
#+static inline int iic_invalid_address(const struct i2c_msg* p) #+{
#+ return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f));
# }
#
#+static inline int iic_address_neq(const struct i2c_msg* p1,
#+ const struct i2c_msg* p2)
#+{
#+ return (p1->addr != p2->addr)
#+ || ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN));
#+}
#
#-//
#-// Description: Implements device specific ioctls. Higher level ioctls can #-// be found in i2c-core.c and are typical of any i2c controller (specifying #-// slave address, timeouts, etc). These ioctls take advantage of any hardware #-// features built into the controller for which this algorithm-adapter set #-// was written. These ioctls allow you to take control of the data and clock #-// lines on the IBM PPC 405 IIC controller and set the either high or low, #-// similar to a GPIO pin.
#-//
#-static int algo_control(struct i2c_adapter *adapter,
#- unsigned int cmd, unsigned long arg)
#-{
#- struct iic_regs *iic;
#- struct i2c_algo_iic_data *adap = adapter->algo_data;
#- struct iic_ibm *adap_priv_data = adap->data;
#- int ret=0;
#- int lines;
#- iic = (struct iic_regs *) adap_priv_data->iic_base;
#-
#- lines = iic_inb(adap, iic->directcntl);
#-
#- if (cmd = IICO_I2C_SDAHIGH) {

#-	      lines = lines & 0x01;
#-	      if( lines ) lines = 0x04;
#-	      else lines = 0;
#-	      iic_outb(adap, iic->directcntl,(0x08|lines));

#- }
#- else if (cmd = IICO_I2C_SDALOW) {
#- lines = lines & 0x01;
#- if( lines ) lines = 0x04;
#- else lines = 0;
#- iic_outb(adap, iic->directcntl,(0x00|lines));
#- }
#- else if (cmd = IICO_I2C_SCLHIGH) {

#-              lines = lines & 0x02;
#-              if( lines ) lines = 0x08;
#-              else lines = 0;
#-              iic_outb(adap, iic->directcntl,(0x04|lines));

#- }
#- else if (cmd = IICO_I2C_SCLLOW) {
#- lines = lines & 0x02;
#- if( lines ) lines = 0x08;
#- else lines = 0;
#- iic_outb(adap, iic->directcntl,(0x00|lines));
#+/*
#+ * Generic master transfer entrypoint.
#+ * Returns the number of processed messages or error (<0)
#+ */
#+static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) #+{
#+ struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap));
#+ volatile struct iic_regs *iic = dev->vaddr;
#+ int i, ret = 0;
#+
#+ DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
#+
#+ if (!num)
#+ return 0;
#+
#+ /* Check the sanity of the passed messages.
#+ * Uhh, generic i2c layer is more suitable place for such code...
#+ */
#+ if (unlikely(iic_invalid_address(&msgs[0]))){
#+ DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx,
#+ msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7);
#+ return -EINVAL;
#+ }
#+ for (i = 0; i < num; ++i){
#+ if (unlikely(msgs[i].len <= 0)){
#+ DBG("%d: invalid len %d in msg[%d]\n", dev->idx,
#+ msgs[i].len, i);
#+ return -EINVAL;
#+ }
#+ if (unlikely(iic_address_neq(&msgs[0], &msgs[i]))){
#+ DBG("%d: invalid addr in msg[%d]\n", dev->idx, i);
#+ return -EINVAL;
#+ }
# }
#- else if (cmd = IICO_I2C_LINEREAD) {
#- ret = lines;
#+
#+ /* Check bus state */
#+ if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){
#+ DBG("%d: iic_xfer, bus is not free\n", dev->idx);
#+
#+ /* Usually it means something serious has happend.
#+ * We *cannot* have unfinished previous transfer
#+ * so it doesn't make any sense to try to stop it.
#+ * Probably we were not able to recover from the
#+ * previous error.
#+ * The only *reasonable* thing I can think of here
#+ * is soft reset. --ebs
#+ */
#+ iic_dev_reset(dev);
#+
#+ if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
#+ DBG("%d: iic_xfer, bus is still not free\n", dev->idx);
#+ return -EREMOTEIO;
#+ }
#+ }
#+ else {
#+ /* Flush master data buffer (just in case) */
#+ out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
# }
#- return ret;
#-}
#+
#+ /* Load slave address */
#+ iic_address(dev, &msgs[0]);
#+
#+ /* Do real transfer */
#+ for (i = 0; i < num && !ret; ++i)
#+ ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1);
#
#+ return ret < 0 ? ret : num;
#+}
#

# static u32 iic_func(struct i2c_adapter *adap)
# {
#-	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
#-	       I2C_FUNC_PROTOCOL_MANGLING; 
#+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
# }
# 
#-
#-/* -----exported algorithm data: -------------------------------------	*/
#-
# static struct i2c_algorithm iic_algo = {
#-	.name		= "IBM on-chip IIC algorithm",
#-	.id		= I2C_ALGO_OCP,
#-	.master_xfer	= iic_xfer,
#-	.algo_control	= algo_control,
#-	.functionality	= iic_func,
#+	.name 		= "IBM IIC algorithm",
#+	.id   		= I2C_ALGO_OCP,
#+	.master_xfer 	= iic_xfer,
#+	.smbus_xfer	= NULL,
#+	.slave_send	= NULL,
#+	.slave_recv	= NULL,
#+	.algo_control	= NULL,
#+	.functionality	= iic_func
# };
# 
#-/* 
#- * registering functions to load algorithms at runtime 
#+/*
#+ * Scan bus for valid 7-bit addresses (ie things that ACK on 1 byte read)
#+ * We only scan range [0x08 - 0x77], all other addresses are reserved anyway
#  */
#+static void __devinit iic_scan_bus(struct ibm_iic_private* dev)
#+{
#+	int found = 0;
#+	char dummy;
#+	struct i2c_msg msg = {
#+		.buf   = &dummy,
#+		.len   = sizeof(dummy),
#+		.flags = I2C_M_RD
#+	};
#+	
#+	printk(KERN_INFO "ibm-iic%d: scanning bus...\n" KERN_INFO, dev->idx);
#+	
#+	for (msg.addr = 8; msg.addr < 0x78; ++msg.addr)
#+		if (iic_xfer(&dev->adap, &msg, 1) = 1){
#+			++found;
#+			printk(" 0x%02x", msg.addr);
#+		}
# 
#+	printk("%sibm-iic%d: %d device(s) detected\n", 
#+		found ? "\n" KERN_INFO : "", dev->idx, found);
#+}
# 
#-//
#-// Description: Register bus structure
#-//
#-int i2c_ocp_add_bus(struct i2c_adapter *adap)
#+/*
#+ * Calculates IICx_CLCKDIV value for a specific OPB clock frequency
#+ */
#+static inline u8 iic_clckdiv(unsigned int opb)
# {
#-	struct i2c_algo_iic_data *iic_adap = adap->algo_data;
#+	/* Compatibility kludge, should go away after all cards
#+	 * are fixed to fill correct value for opbfreq.
#+	 * Previous driver version used hardcoded divider value 4,
#+	 * it corresponds to OPB frequency from the range (40, 50] MHz
#+	 */
#+	if (!opb){
#+		printk(KERN_WARNING "ibm-iic: using compatibility value for OPB freq,"
#+			" fix your board specific setup\n");
#+		opb = 50000000;
#+	}
# 
#-	DEB2(printk(KERN_DEBUG "i2c-algo-iic.o: hw routines for %s registered.\n",
#-	            adap->name));
#+	/* Convert to MHz */
#+	opb /= 1000000;
#+	
#+	if (opb < 20 || opb > 150){
#+		printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
#+			opb);
#+		opb = opb < 20 ? 20 : 150;
#+	}
#+	return (u8)((opb + 9) / 10 - 1);
#+}
#+
#+/*
#+ * Register single IIC interface
#+ */
#+static int __devinit iic_probe(struct ocp_device *ocp){
#+
#+	struct ibm_iic_private* dev;
#+	struct i2c_adapter* adap;
#+	int ret;
#+	bd_t* bd = (bd_t*)&__res;
#+	
#+	if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){
#+		printk(KERN_CRIT "ibm-iic: failed to allocate device data\n");
#+		return -ENOMEM;
#+	}
# 
#-	/* register new adapter to i2c module... */
#+	memset(dev, 0, sizeof(*dev));
#+	dev->idx = ocp->num;
#+	ocp_set_drvdata(ocp, dev);
#+	
#+	if (!(dev->vaddr = ioremap(ocp->paddr, sizeof(struct iic_regs)))){
#+		printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
#+			dev->idx);
#+		ret = -ENXIO;
#+		goto fail2;
#+	}
#+	
#+	init_waitqueue_head(&dev->wq);
# 
#-	adap->id |= iic_algo.id;
#+	dev->irq = iic_force_poll ? -1 : ocp->irq;
#+	if (dev->irq >= 0){
#+		/* Disable interrupts until we finish intialization,
#+		   assumes level-sensitive IRQ setup...
#+		 */
#+		iic_interrupt_mode(dev, 0);
#+		if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
#+			printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", 
#+				dev->idx, dev->irq);
#+			/* Fallback to the polling mode */	
#+			dev->irq = -1;
#+		}
#+	}
#+	
#+	if (dev->irq < 0)
#+		printk(KERN_WARNING "ibm-iic%d: using polling mode\n", 
#+			dev->idx);
#+		
#+	/* Board specific settings */
#+	BUG_ON(dev->idx >= sizeof(bd->bi_iic_fast) / sizeof(bd->bi_iic_fast[0]));
#+	dev->fast_mode = iic_force_fast ? 1 : bd->bi_iic_fast[dev->idx];
#+	
#+	/* clckdiv is the same for *all* IIC interfaces, 
#+	 * but I'd rather make a copy than introduce another global. --ebs
#+	 */
#+	dev->clckdiv = iic_clckdiv(bd->bi_opb_busfreq);
#+	DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
#+	
#+	/* Initialize IIC interface */
#+	iic_dev_init(dev);
#+	
#+	/* Register it with i2c layer */
#+	adap = &dev->adap;
#+	strcpy(adap->dev.name, "IBM IIC");
#+	i2c_set_adapdata(adap, dev);
#+	adap->id = I2C_HW_OCP | iic_algo.id;
# 	adap->algo = &iic_algo;
#+	adap->client_register = NULL;
#+	adap->client_unregister = NULL;
#+	adap->timeout = 1;
#+	adap->retries = 1;
#+
#+	if ((ret = i2c_add_adapter(adap)) != 0){
#+		printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
#+			dev->idx);
#+		goto fail;
#+	}
#+	
#+	printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
#+		dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
# 
#-	adap->timeout = 100;	/* default values, should	*/
#-	adap->retries = 3;		/* be replaced by defines	*/
#+	/* Scan bus if requested by user */
#+	if (iic_scan)
#+		iic_scan_bus(dev);
# 
#-	iic_init(iic_adap);
#-	i2c_add_adapter(adap);
# 	return 0;
#-}
# 
#+fail:	
#+	if (dev->irq >= 0){
#+		iic_interrupt_mode(dev, 0);
#+		free_irq(dev->irq, dev);
#+	}	
#+
#+	iounmap((void*)dev->vaddr);
#+fail2:	
#+	ocp_set_drvdata(ocp, 0);
#+	kfree(dev);	
#+	return ret;
#+}
# 
#-//
#-// Done
#-//
#-int i2c_ocp_del_bus(struct i2c_adapter *adap)
#+/*
#+ * Cleanup initialized IIC interface
#+ */
#+static void __devexit iic_remove(struct ocp_device *ocp)
# {
#-	return i2c_del_adapter(adap);
#+	struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
#+	BUG_ON(dev = NULL);
#+	if (i2c_del_adapter(&dev->adap)){
#+		printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
#+			dev->idx);
#+		/* That's *very* bad, just shutdown IRQ ... */
#+		if (dev->irq >= 0){
#+		    iic_interrupt_mode(dev, 0);	
#+		    free_irq(dev->irq, dev);
#+		    dev->irq = -1;
#+		}
#+	} else {
#+		if (dev->irq >= 0){
#+		    iic_interrupt_mode(dev, 0);	
#+		    free_irq(dev->irq, dev);
#+		}
#+		iounmap((void*)dev->vaddr);
#+		kfree(dev);
#+	}
# }
# 
#+static struct ocp_device_id ibm_iic_ids[] __devinitdata = 
#+{
#+	{ .vendor = OCP_VENDOR_IBM, .device = OCP_FUNC_IIC },
#+	{ .vendor = OCP_VENDOR_INVALID }
#+};
# 
#-EXPORT_SYMBOL(i2c_ocp_add_bus);
#-EXPORT_SYMBOL(i2c_ocp_del_bus);
#+MODULE_DEVICE_TABLE(ocp, ibm_iic_ids);
# 
#-//
#-// The MODULE_* macros resolve to nothing if MODULES is not defined
#-// when this file is compiled.
#-//
#-MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
#-MODULE_DESCRIPTION("PPC 405 iic algorithm");
#-MODULE_LICENSE("GPL");
#+static struct ocp_driver ibm_iic_driver #+{
#+	.name 		= "ocp_iic",
#+	.id_table	= ibm_iic_ids,
#+	.probe		= iic_probe,
#+	.remove		= __devexit_p(iic_remove),
#+#if defined(CONFIG_PM)
#+	.suspend	= NULL,
#+	.resume		= NULL,
#+#endif
#+};
# 
#-MODULE_PARM(i2c_debug,"i");
#+static int __init iic_init(void)
#+{
#+	printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n");
#+	return ocp_module_init(&ibm_iic_driver);
#+}
# 
#-MODULE_PARM_DESC(i2c_debug,
#-        "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
#+static void __exit iic_exit(void)
#+{
#+	ocp_unregister_driver(&ibm_iic_driver);
#+}
# 
#+module_init(iic_init);
#+module_exit(iic_exit);
#
#--- 1.2/drivers/i2c/i2c-algo-ibm_ocp.h	Sat Sep 21 13:00:21 2002
#+++ 1.4/drivers/i2c/i2c-ibm_iic.h	Fri Sep 12 12:31:23 2003
#@@ -1,55 +1,124 @@
#-/* ------------------------------------------------------------------------- */
#-/* i2c-algo-ibm_ocp.h i2c driver algorithms for IBM PPC 405 IIC adapters         */
#-/* ------------------------------------------------------------------------- */
#-/*   Copyright (C) 1995-97 Simon G. Vogl
#-                   1998-99 Hans Berglund
#-
#-    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.                */
#-/* ------------------------------------------------------------------------- */
#-
#-/* With some changes from Ky?sti M?lkki <[email protected]> and even
#-   Frodo Looijaard <[email protected]> */
#-
#-/* Modifications by MontaVista Software, August 2000
#-   Changes made to support the IIC peripheral on the IBM PPC 405 */
#-
#-#ifndef I2C_ALGO_IIC_H
#-#define I2C_ALGO_IIC_H 1
#-
#-/* --- Defines for pcf-adapters ---------------------------------------	*/
#-#include <linux/i2c.h>
#-
#-struct i2c_algo_iic_data {
#-	struct iic_regs *data;		/* private data for lolevel routines	*/
#-	void (*setiic) (void *data, int ctl, int val);
#-	int  (*getiic) (void *data, int ctl);
#-	int  (*getown) (void *data);
#-	int  (*getclock) (void *data);
#-	void (*waitforpin) (void *data);     
#-
#-	/* local settings */
#-	int udelay;
#-	int mdelay;
#-	int timeout;
#+/*
#+ * drivers/i2c/i2c-ibm_iic.h
#+ *
#+ * Support for the IIC peripheral on IBM PPC 4xx
#+ * 
#+ * Copyright (c) 2003 Zultys Technologies.
#+ * Eugene Surovegin <[email protected]> or <[email protected]>
#+ *
#+ * Based on original work by 
#+ * 	Ian DaSilva  <[email protected]>
#+ *      Armin Kuster <[email protected]>
#+ * 	Matt Porter  <[email protected]>
#+ *
#+ *      Copyright 2000-2003 MontaVista Software Inc.
#+ *
#+ * 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.
#+ *
#+ */
#+#ifndef __I2C_IBM_IIC_H_
#+#define __I2C_IBM_IIC_H_
#+
#+#include <linux/config.h>
#+#include <linux/i2c.h> 
#+
#+struct iic_regs {
#+	u16 mdbuf;
#+	u16 sbbuf;
#+	u8 lmadr;
#+	u8 hmadr;
#+	u8 cntl;
#+	u8 mdcntl;
#+	u8 sts;
#+	u8 extsts;
#+	u8 lsadr;
#+	u8 hsadr;
#+	u8 clkdiv;
#+	u8 intmsk;
#+	u8 xfrcnt;
#+	u8 xtcntlss;
#+	u8 directcntl;
# };
# 
#+struct ibm_iic_private {
#+	struct i2c_adapter adap;
#+	volatile struct iic_regs *vaddr;
#+	wait_queue_head_t wq;
#+	int idx;
#+	int irq;
#+	int fast_mode;
#+	u8  clckdiv;
#+};
# 
#-#define I2C_IIC_ADAP_MAX	16
#-
#+/* IICx_CNTL register */
#+#define CNTL_HMT	0x80
#+#define CNTL_AMD	0x40
#+#define CNTL_TCT_MASK	0x30
#+#define CNTL_TCT_SHIFT	4
#+#define CNTL_RPST	0x08
#+#define CNTL_CHT	0x04 
#+#define CNTL_RW		0x02
#+#define CNTL_PT		0x01
#+
#+/* IICx_MDCNTL register */
#+#define MDCNTL_FSDB	0x80
#+#define MDCNTL_FMDB	0x40
#+#define MDCNTL_EGC	0x20
#+#define MDCNTL_FSM	0x10
#+#define MDCNTL_ESM	0x08
#+#define MDCNTL_EINT	0x04
#+#define MDCNTL_EUBS	0x02
#+#define MDCNTL_HSCL	0x01
#+
#+/* IICx_STS register */
#+#define STS_SSS		0x80
#+#define STS_SLPR	0x40
#+#define STS_MDBS	0x20
#+#define STS_MDBF	0x10
#+#define STS_SCMP	0x08
#+#define STS_ERR		0x04
#+#define STS_IRQA	0x02
#+#define STS_PT		0x01
#+
#+/* IICx_EXTSTS register */
#+#define EXTSTS_IRQP	0x80
#+#define EXTSTS_BCS_MASK	0x70
#+#define   EXTSTS_BCS_FREE  0x40
#+#define EXTSTS_IRQD	0x08
#+#define EXTSTS_LA	0x04
#+#define EXTSTS_ICT	0x02
#+#define EXTSTS_XFRA	0x01
#+
#+/* IICx_INTRMSK register */
#+#define INTRMSK_EIRC	0x80
#+#define INTRMSK_EIRS	0x40
#+#define INTRMSK_EIWC	0x20
#+#define INTRMSK_EIWS	0x10
#+#define INTRMSK_EIHE	0x08
#+#define INTRMSK_EIIC	0x04
#+#define INTRMSK_EITA	0x02
#+#define INTRMSK_EIMTC	0x01
#+
#+/* IICx_XFRCNT register */
#+#define XFRCNT_MTC_MASK	0x07
#+
#+/* IICx_XTCNTLSS register */
#+#define XTCNTLSS_SRC	0x80
#+#define XTCNTLSS_SRS	0x40
#+#define XTCNTLSS_SWC	0x20
#+#define XTCNTLSS_SWS	0x10
#+#define XTCNTLSS_SRST	0x01
#+
#+/* IICx_DIRECTCNTL register */
#+#define DIRCNTL_SDAC	0x08
#+#define DIRCNTL_SCC	0x04
#+#define DIRCNTL_MSDA	0x02
#+#define DIRCNTL_MSC	0x01
# 
#-int i2c_ocp_add_bus(struct i2c_adapter *);
#-int i2c_ocp_del_bus(struct i2c_adapter *);
#+/* Check if we really control the I2C bus and bus is free */
#+#define DIRCTNL_FREE(v)	(((v) & 0x0f) = 0x0f)
# 
#-#endif /* I2C_ALGO_IIC_H */
#+#endif /* __I2C_IBM_IIC_H_ */
#
#--- 1.12/drivers/i2c/Makefile	Sun Jun 15 16:57:44 2003
#+++ 1.13/drivers/i2c/Makefile	Fri Sep 12 12:30:34 2003
#@@ -16,6 +16,7 @@
# obj-$(CONFIG_ITE_I2C_ADAP)	+= i2c-adap-ite.o
# obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
# obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
#+obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
# obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
# obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
# obj-y				+= busses/ chips/
#
#--- 1.14/drivers/i2c/Kconfig	Tue Aug 26 11:58:28 2003
#+++ 1.15/drivers/i2c/Kconfig	Fri Sep 12 12:30:34 2003
#@@ -203,13 +203,9 @@
# 	tristate "Embedded Planet RPX Lite/Classic suppoort"
# 	depends on (RPXLITE || RPXCLASSIC) && I2C_ALGO8XX
# 
#-config I2C_IBM_OCP_ALGO
#-	tristate "IBM on-chip I2C Algorithm"
#+config I2C_IBM_IIC
#+	tristate "IBM IIC I2C"
# 	depends on IBM_OCP && I2C
#-
#-config I2C_IBM_OCP_ADAP
#-	tristate "IBM on-chip I2C Adapter"
#-	depends on I2C_IBM_OCP_ALGO
# 
# config I2C_IOP3XX
# 	tristate "Intel XScale IOP3xx on-chip I2C interface"
#

# Diff checksum5f2d45

# Patch vers: 1.3
# Patch type: REGULAR

= ChangeSet = [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 [email protected]|ChangeSet|20030912042307|22597
D 1.1316 03/09/12 12:36:24-07:00 [email protected] +4 -0 B [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 C
c I2C: Add rewritten PPC4xx I2C driver
K 23626
P ChangeSet
------------------------------------------------

0a0

Quoted 4 lines
[email protected][torvalds]|drivers/i2c/Kconfig|20021030043228|25271|93781e6749f2f6e9 [email protected]|drivers/i2c/Kconfig|20030912193034|46908
[email protected]|drivers/i2c/Makefile|20020205174018|59980|699ee8af74f52ec9 [email protected]|drivers/i2c/Makefile|20030912193034|58226
[email protected]|drivers/i2c/i2c-algo-ibm_ocp.c|20020814030432|31847|15febbe23542f55 [email protected]|drivers/i2c/i2c-ibm_iic.c|20030912193123|39319
[email protected]|drivers/i2c/i2c-algo-ibm_ocp.h|20020814030433|04184|75cb964c98b96883 [email protected]|drivers/i2c/i2c-ibm_iic.h|20030912193123|13276

= drivers/i2c/i2c-ibm_iic.c = [email protected]|drivers/i2c/i2c-algo-ibm_ocp.c|20020814030432|31847|15febbe23542f55 [email protected][torvalds]|drivers/i2c/i2c-algo-ibm_ocp.c|20030311202111|03164 D 1.6 03/09/12 12:21:03-07:00 [email protected] +0 -0
B [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 c Rename: drivers/i2c/i2c-algo-ibm_ocp.c -> drivers/i2c/i2c-ibm_iic.c K 1891
O -rw-rw-r--
P drivers/i2c/i2c-ibm_iic.c
------------------------------------------------

[email protected]|drivers/i2c/i2c-ibm_iic.c|20030912192103|01891 D 1.7 03/09/12 12:31:23-07:00 [email protected] +649 -820 B [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 C
c Rewritten PPC4xx I2C driver
K 39319
O -rw-rw-r--
P drivers/i2c/i2c-ibm_iic.c
------------------------------------------------

D2 53
I54 28
* drivers/i2c/i2c-ibm_iic.c
*
* Support for the IIC peripheral on IBM PPC 4xx
*
* Copyright (c) 2003 Zultys Technologies.
* Eugene Surovegin <[email protected]> or <[email protected]> *
* Based on original work by
* Ian DaSilva <[email protected]>
* Armin Kuster <[email protected]>
* Matt Porter <[email protected]>
*
* Copyright 2000-2003 MontaVista Software Inc.
*
* Original driver version was highly leveraged from i2c-elektor.c *
* Copyright 1995-97 Simon G. Vogl
* 1998-99 Hans Berglund
*
* With some changes from Ky?sti M?lkki <[email protected]>
* and even Frodo Looijaard <[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.
*
*/
I55 2
#include <linux/kernel.h>
#include <linux/ioport.h>
D59 2
I60 3
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/io.h>
D62 1
I62 1
#include <linux/i2c-id.h>
I63 1
#include <asm/ibm4xx.h>
I64 1
#include "i2c-ibm_iic.h"
D66 10
I75 1
#define DRIVER_VERSION "2.0"
I76 2
MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); MODULE_LICENSE("GPL");
D78 14
I91 11
static int iic_scan = 0;
MODULE_PARM(iic_scan, "i");
MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus"); \
static int iic_force_poll = 0;
MODULE_PARM(iic_force_poll, "i"); MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
\
static int iic_force_fast = 0;
MODULE_PARM(iic_force_fast, "i"); MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)"); D93 2
I94 1
#define DBG_LEVEL 0
D96 3
I98 3
#ifdef DBG
#undef DBG
#endif
D100 1
I100 3
#ifdef DBG2
#undef DBG2
#endif
I101 27
#if DBG_LEVEL > 0
# define DBG(x...) printk(KERN_DEBUG "ibm-iic" ##x)
#else
# define DBG(x...) ((void)0)
#endif
#if DBG_LEVEL > 1
# define DBG2(x...) DBG( ##x )
#else
# define DBG2(x...) ((void)0)
#endif
#if DBG_LEVEL > 2
static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)

{
	volatile struct iic_regs *iic = dev->vaddr;
	printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header);
	printk(KERN_DEBUG "  cntl     = 0x%02x, mdcntl = 0x%02x\n"
	       KERN_DEBUG "  sts      = 0x%02x, extsts = 0x%02x\n"
	       KERN_DEBUG "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
	       KERN_DEBUG "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",
		in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), 
		in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), 
		in_8(&iic->xtcntlss), in_8(&iic->directcntl));
}

# define DUMP_REGS(h,dev) dump_iic_regs((h),(dev))
#else
# define DUMP_REGS(h,dev) ((void)0)
#endif
D103 4
I106 2
/* Enable/disable interrupt generation */
static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable) D108 1
I108 1

	out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0);

D110 7
I116 5

/*
* Initialize IIC interface.
*/
static void iic_dev_init(struct ibm_iic_private* dev) D118 16
I133 1

	volatile struct iic_regs *iic = dev->vaddr;
D135 20
I154 24
	DBG("%d: init\n", dev->idx);
	
	/* Clear master address */
	out_8(&iic->lmadr, 0);
	out_8(&iic->hmadr, 0);
\
	/* Clear slave address */
	out_8(&iic->lsadr, 0);
	out_8(&iic->hsadr, 0);
\
	/* Clear status & extended status */
	out_8(&iic->sts, STS_SCMP | STS_IRQA);
	out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | EXTSTS_LA
			    | EXTSTS_ICT | EXTSTS_XFRA);
\
	/* Set clock divider */
	out_8(&iic->clkdiv, dev->clckdiv);
\
	/* Clear transfer count */
	out_8(&iic->xfrcnt, 0);
\
	/* Clear extended control and status */
	out_8(&iic->xtcntlss, XTCNTLSS_SRC | XTCNTLSS_SRS | XTCNTLSS_SWC
			    | XTCNTLSS_SWS);
D156 3
I158 5
	/* Clear control register */
	out_8(&iic->cntl, 0);
	
	/* Enable interrupts if possible */
	iic_interrupt_mode(dev, dev->irq >= 0);
D160 2
I161 3
	/* Set mode control */
	out_8(&iic->mdcntl, MDCNTL_FMDB | MDCNTL_EINT | MDCNTL_EUBS
			    | (dev->fast_mode ? MDCNTL_FSM : 0));
D163 2
I164 1
	DUMP_REGS("iic_init", dev);

D167 7
I173 4
/*
* Reset IIC interface
*/
static void iic_dev_reset(struct ibm_iic_private* dev) I174 42

	volatile struct iic_regs *iic = dev->vaddr;
	int i;
	u8 dc;
	
	DBG("%d: soft reset\n", dev->idx);
	DUMP_REGS("reset", dev);
	
    	/* Place chip in the reset state */
	out_8(&iic->xtcntlss, XTCNTLSS_SRST);
	
	/* Check if bus is free */
	dc = in_8(&iic->directcntl);	
	if (!DIRCTNL_FREE(dc)){
		DBG("%d: trying to regain bus control\n", dev->idx);
	
		/* Try to set bus free state */
		out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);	
	
		/* Wait until we regain bus control */
		for (i = 0; i < 100; ++i){
			dc = in_8(&iic->directcntl);
			if (DIRCTNL_FREE(dc))
				break;
			
			/* Toggle SCL line */
			dc ^= DIRCNTL_SCC;
			out_8(&iic->directcntl, dc);
			udelay(10);
			dc ^= DIRCNTL_SCC;
			out_8(&iic->directcntl, dc);
			
			/* be nice */
			cond_resched();
		}
	}
	
	/* Remove reset */
	out_8(&iic->xtcntlss, 0);
	
	/* Reinitialize interface */
	iic_dev_init(dev);
}

D176 9
I184 17
/*
* IIC interrupt handler
*/
static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs)

{
	struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id;
	volatile struct iic_regs* iic = dev->vaddr;
	
	DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", 
	     dev->idx, in_8(&iic->sts), in_8(&iic->extsts));
	
	/* Acknowledge IRQ and wakeup iic_wait_for_tc */
	out_8(&iic->sts, STS_IRQA | STS_SCMP);
	wake_up_interruptible(&dev->wq);
	
	return IRQ_HANDLED;
}

D186 43
I228 29
/*
* Get master transfer result and clear errors if any.
* Returns the number of actually transferred bytes or error (<0) */
static int iic_xfer_result(struct ibm_iic_private* dev)

{
	volatile struct iic_regs *iic = dev->vaddr;	
	
	if (unlikely(in_8(&iic->sts) & STS_ERR)){
		DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, 
			in_8(&iic->extsts));
				
		/* Clear errors and possible pending IRQs */
		out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | 
			EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA);
			
		/* Flush master data buffer */
		out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
		
		/* Is bus free?
		 * If error happened during combined xfer
		 * IIC interface is usually stuck in some strange
		 * state, the only way out - soft reset.
		 */
		if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
			DBG("%d: bus is stuck, resetting\n", dev->idx);
			iic_dev_reset(dev);
		}
		return -EREMOTEIO;
D231 1
I231 1
		return in_8(&iic->xfrcnt) & XFRCNT_MTC_MASK;

I233 25
/*
* Try to abort active transfer.
*/
static void iic_abort_xfer(struct ibm_iic_private* dev)

{
	volatile struct iic_regs *iic = dev->vaddr;
	unsigned long x;
	
	DBG("%d: iic_abort_xfer\n", dev->idx);
	
	out_8(&iic->cntl, CNTL_HMT);
	
	/*
	 * Wait for the abort command to complete.
	 * It's not worth to be optimized, just poll (timeout >= 1 tick)
	 */
	x = jiffies + 2;
	while ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
		if (time_after(jiffies, x)){
			DBG("%d: abort timeout, resetting...\n", dev->idx);
			iic_dev_reset(dev);
			return;
		}
		schedule();
	}
D235 38
I272 2
	/* Just to clear errors */
	iic_xfer_result(dev);

D275 316
I590 28
/*
* Wait for master transfer to complete.
* It puts current process to sleep until we get interrupt or timeout expires.
* Returns the number of transferred bytes or error (<0)
*/

static int iic_wait_for_tc(struct ibm_iic_private* dev){
	
	volatile struct iic_regs *iic = dev->vaddr;
	int ret = 0;
	
	if (dev->irq >= 0){
		/* Interrupt mode */
		wait_queue_t wait;
    		init_waitqueue_entry(&wait, current);
		
		add_wait_queue(&dev->wq, &wait);
		set_current_state(TASK_INTERRUPTIBLE);
		if (in_8(&iic->sts) & STS_PT)
			schedule_timeout(dev->adap.timeout * HZ);
		set_current_state(TASK_RUNNING);
		remove_wait_queue(&dev->wq, &wait);
		
		if (unlikely(signal_pending(current))){
			DBG("%d: wait interrupted\n", dev->idx);
			ret = -ERESTARTSYS;
		} else if (unlikely(in_8(&iic->sts) & STS_PT)){
			DBG("%d: wait timeout\n", dev->idx);
			ret = -ETIMEDOUT;
D592 15
I606 10
	}
	else {
		/* Polling mode */
		unsigned long x = jiffies + dev->adap.timeout * HZ;
		
		while (in_8(&iic->sts) & STS_PT){
			if (unlikely(time_after(jiffies, x))){
				DBG("%d: poll timeout\n", dev->idx);
				ret = -ETIMEDOUT;
				break;

D608 2
I609 5

			if (unlikely(signal_pending(current))){
				DBG("%d: poll interrupted\n", dev->idx);
				ret = -ERESTARTSYS;
				break;
D611 1
I611 2
			schedule();
		}	

D613 2
I614 9

	if (unlikely(ret < 0))
		iic_abort_xfer(dev);
	else
		ret = iic_xfer_result(dev);
	
	DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret);
	
	return ret;

D617 49
I665 49
/*
* Low level master transfer routine
*/
static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
int combined_xfer)

{
	volatile struct iic_regs *iic = dev->vaddr;
	char* buf = pm->buf;
	int i, j, loops, ret = 0;
	int len = pm->len;
\
	u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT;
	if (pm->flags & I2C_M_RD)
		cntl |= CNTL_RW;
	
	loops = (len + 3) / 4;
	for (i = 0; i < loops; ++i, len -= 4){
		int count = len > 4 ? 4 : len;
		u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT);
		
		if (!(cntl & CNTL_RW))
			for (j = 0; j < count; ++j)
				out_8((volatile u8*)&iic->mdbuf, *buf++);
		
		if (i < loops - 1)
			cmd |= CNTL_CHT;
		else if (combined_xfer)
			cmd |= CNTL_RPST;
		
		DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd);
		
		/* Start transfer */
		out_8(&iic->cntl, cmd);
		
		/* Wait for completion */
		ret = iic_wait_for_tc(dev);
\
		if (unlikely(ret < 0))
			break;
		else if (unlikely(ret != count)){
			DBG("%d: xfer_bytes, requested %d, transfered %d\n", 
				dev->idx, count, ret);
			
			/* If it's not a last part of xfer, abort it */
			if (combined_xfer || (i < loops - 1))
    				iic_abort_xfer(dev);
				
			ret = -EREMOTEIO;
			break;				

D667 20
I686 7

		if (cntl & CNTL_RW)
			for (j = 0; j < count; ++j)
				*buf++ = in_8((volatile u8*)&iic->mdbuf);
	}
	
	return ret > 0 ? 0 : ret;

I688 21
/*
* Set target slave address for master transfer
*/
static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg)

{
	volatile struct iic_regs *iic = dev->vaddr;
	u16 addr = msg->addr;
	
	DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, 
		addr, msg->flags & I2C_M_TEN ? 10 : 7);
	
	if (msg->flags & I2C_M_TEN){
	    out_8(&iic->cntl, CNTL_AMD);
	    out_8(&iic->lmadr, addr);
	    out_8(&iic->hmadr, 0xf0 | ((addr >> 7) & 0x06));
	}
	else {
	    out_8(&iic->cntl, 0);
	    out_8(&iic->lmadr, addr << 1);
	}
}
D690 85
I774 3
static inline int iic_invalid_address(const struct i2c_msg* p)
{
	return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f));
I776 6
static inline int iic_address_neq(const struct i2c_msg* p1, 
				  const struct i2c_msg* p2)
{
	return (p1->addr != p2->addr) 
		|| ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN));
} 

D778 44
I821 33
/*
* Generic master transfer entrypoint.
* Returns the number of processed messages or error (<0)
*/
static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)

{
    	struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap));
	volatile struct iic_regs *iic = dev->vaddr;
	int i, ret = 0;
	
	DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
	
	if (!num)
		return 0;
	
	/* Check the sanity of the passed messages.
	 * Uhh, generic i2c layer is more suitable place for such code...
	 */
	if (unlikely(iic_invalid_address(&msgs[0]))){
		DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx, 
			msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7);
		return -EINVAL;
	}		
	for (i = 0; i < num; ++i){
		if (unlikely(msgs[i].len <= 0)){
			DBG("%d: invalid len %d in msg[%d]\n", dev->idx, 
				msgs[i].len, i);
			return -EINVAL;
		}
		if (unlikely(iic_address_neq(&msgs[0], &msgs[i]))){
			DBG("%d: invalid addr in msg[%d]\n", dev->idx, i);
			return -EINVAL;
		}

D823 2
I824 23

	/* Check bus state */
	if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){
		DBG("%d: iic_xfer, bus is not free\n", dev->idx);
		
		/* Usually it means something serious has happend.
		 * We *cannot* have unfinished previous transfer
		 * so it doesn't make any sense to try to stop it.
		 * Probably we were not able to recover from the 
		 * previous error.
		 * The only *reasonable* thing I can think of here
		 * is soft reset.  --ebs
		 */
		iic_dev_reset(dev);
		
		if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
			DBG("%d: iic_xfer, bus is still not free\n", dev->idx);
			return -EREMOTEIO;
		}
	} 
	else {
		/* Flush master data buffer (just in case) */
		out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);

D826 2
I827 7

	/* Load slave address */
	iic_address(dev, &msgs[0]);
	
	/* Do real transfer */
    	for (i = 0; i < num && !ret; ++i)
		ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1);
I828 2
	return ret < 0 ? ret : num;
}
D832 2
I833 1
	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
D836 3
D840 5
I844 8
	.name 		= "IBM IIC algorithm",
	.id   		= I2C_ALGO_OCP,
	.master_xfer 	= iic_xfer,
	.smbus_xfer	= NULL,
	.slave_send	= NULL,
	.slave_recv	= NULL,
	.algo_control	= NULL,
	.functionality	= iic_func

D847 2
I848 3
/*
* Scan bus for valid 7-bit addresses (ie things that ACK on 1 byte read)
* We only scan range [0x08 - 0x77], all other addresses are reserved anyway
I849 17
static void __devinit iic_scan_bus(struct ibm_iic_private* dev)

{
	int found = 0;
	char dummy;
	struct i2c_msg msg = {
		.buf   = &dummy,
		.len   = sizeof(dummy),
		.flags = I2C_M_RD
	};
	
	printk(KERN_INFO "ibm-iic%d: scanning bus...\n" KERN_INFO, dev->idx);
	
	for (msg.addr = 8; msg.addr < 0x78; ++msg.addr)
		if (iic_xfer(&dev->adap, &msg, 1) = 1){
			++found;
			printk(" 0x%02x", msg.addr);
		}
I850 3
	printk("%sibm-iic%d: %d device(s) detected\n", 
		found ? "\n" KERN_INFO : "", dev->idx, found);
}

D852 4
I855 4
/*
* Calculates IICx_CLCKDIV value for a specific OPB clock frequency */
static inline u8 iic_clckdiv(unsigned int opb)
D857 1
I857 10

	/* Compatibility kludge, should go away after all cards
	 * are fixed to fill correct value for opbfreq.
	 * Previous driver version used hardcoded divider value 4,
	 * it corresponds to OPB frequency from the range (40, 50] MHz
	 */
	if (!opb){
		printk(KERN_WARNING "ibm-iic: using compatibility value for OPB freq,"
			" fix your board specific setup\n");
		opb = 50000000;
	}
D859 2
I860 25
	/* Convert to MHz */
	opb /= 1000000;
	
	if (opb < 20 || opb > 150){
		printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
			opb);
		opb = opb < 20 ? 20 : 150;
	}
	return (u8)((opb + 9) / 10 - 1);
}

\
/*
* Register single IIC interface
*/
static int __devinit iic_probe(struct ocp_device *ocp){

\
	struct ibm_iic_private* dev;
	struct i2c_adapter* adap;
	int ret;
	bd_t* bd = (bd_t*)&__res;
	
	if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){
		printk(KERN_CRIT "ibm-iic: failed to allocate device data\n");
		return -ENOMEM;
	}
D862 1
I862 12
	memset(dev, 0, sizeof(*dev));
	dev->idx = ocp->num;
	ocp_set_drvdata(ocp, dev);
	
	if (!(dev->vaddr = ioremap(ocp->paddr, sizeof(struct iic_regs)))){
		printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
			dev->idx);
		ret = -ENXIO;
		goto fail2;
	}
	
	init_waitqueue_head(&dev->wq);
D864 1
I864 36
	dev->irq = iic_force_poll ? -1 : ocp->irq;
	if (dev->irq >= 0){
		/* Disable interrupts until we finish intialization,
		   assumes level-sensitive IRQ setup...
		 */
		iic_interrupt_mode(dev, 0);
		if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
			printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", 
				dev->idx, dev->irq);
			/* Fallback to the polling mode */	
			dev->irq = -1;
		}
	}
	
	if (dev->irq < 0)
		printk(KERN_WARNING "ibm-iic%d: using polling mode\n", 
			dev->idx);
		
	/* Board specific settings */
	BUG_ON(dev->idx >= sizeof(bd->bi_iic_fast) / sizeof(bd->bi_iic_fast[0]));
	dev->fast_mode = iic_force_fast ? 1 : bd->bi_iic_fast[dev->idx];
	
	/* clckdiv is the same for *all* IIC interfaces, 
	 * but I'd rather make a copy than introduce another global. --ebs
	 */
	dev->clckdiv = iic_clckdiv(bd->bi_opb_busfreq);
	DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
	
	/* Initialize IIC interface */
	iic_dev_init(dev);
	
	/* Register it with i2c layer */
	adap = &dev->adap;
	strcpy(adap->dev.name, "IBM IIC");
	i2c_set_adapdata(adap, dev);
	adap->id = I2C_HW_OCP | iic_algo.id;
I865 13
	adap->client_register = NULL;
	adap->client_unregister = NULL;
	adap->timeout = 1;
	adap->retries = 1;
\
	if ((ret = i2c_add_adapter(adap)) != 0){
		printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
			dev->idx);
		goto fail;
	}
	
	printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
		dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
D867 2
I868 3
	/* Scan bus if requested by user */
	if (iic_scan)
		iic_scan_bus(dev);

D870 2
D873 1
I874 12
fail:

	if (dev->irq >= 0){
		iic_interrupt_mode(dev, 0);
		free_irq(dev->irq, dev);
	}	
\
	iounmap((void*)dev->vaddr);
fail2:	
	ocp_set_drvdata(ocp, 0);
	kfree(dev);	
	return ret;
}

D876 4
I879 4
/*
* Cleanup initialized IIC interface
*/
static void __devexit iic_remove(struct ocp_device *ocp) D881 1
I881 19

	struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
	BUG_ON(dev = NULL);
	if (i2c_del_adapter(&dev->adap)){
		printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
			dev->idx);
		/* That's *very* bad, just shutdown IRQ ... */
		if (dev->irq >= 0){
		    iic_interrupt_mode(dev, 0);	
		    free_irq(dev->irq, dev);
		    dev->irq = -1;
		}
	} else {
		if (dev->irq >= 0){
		    iic_interrupt_mode(dev, 0);	
		    free_irq(dev->irq, dev);
		}
		iounmap((void*)dev->vaddr);
		kfree(dev);
	}
I883 5
static struct ocp_device_id ibm_iic_ids[] __devinitdata = 
{
	{ .vendor = OCP_VENDOR_IBM, .device = OCP_FUNC_IIC },
	{ .vendor = OCP_VENDOR_INVALID }
};

D885 2
I886 1
MODULE_DEVICE_TABLE(ocp, ibm_iic_ids);
D888 7
I894 11

static struct ocp_driver ibm_iic_driver {
	.name 		= "ocp_iic",
	.id_table	= ibm_iic_ids,
	.probe		= iic_probe,
	.remove		= __devexit_p(iic_remove),
#if defined(CONFIG_PM)
	.suspend	= NULL,
	.resume		= NULL,

#endif
};
D896 1
I896 5
static int __init iic_init(void)

{
	printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n");
	return ocp_module_init(&ibm_iic_driver);
}
D898 2
I899 4
static void __exit iic_exit(void)
{
	ocp_unregister_driver(&ibm_iic_driver);
}

I900 2
module_init(iic_init);
module_exit(iic_exit);

= drivers/i2c/i2c-ibm_iic.h = [email protected]|drivers/i2c/i2c-algo-ibm_ocp.h|20020814030433|04184|75cb964c98b96883 [email protected][torvalds]|drivers/i2c/i2c-algo-ibm_ocp.h|20021230195059|19958 D 1.3 03/09/12 12:21:10-07:00 [email protected] +0 -0
B [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 c Rename: drivers/i2c/i2c-algo-ibm_ocp.h -> drivers/i2c/i2c-ibm_iic.h
K 48109
O -rw-rw-r--
P drivers/i2c/i2c-ibm_iic.h
------------------------------------------------

[email protected]|drivers/i2c/i2c-ibm_iic.h|20030912192110|48109 D 1.4 03/09/12 12:31:23-07:00 [email protected] +119 -50 B [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 C
c Rewritten PPC4xx I2C driver
K 13276
O -rw-rw-r--
P drivers/i2c/i2c-ibm_iic.h
------------------------------------------------

D1 45
I45 43
/*
* drivers/i2c/i2c-ibm_iic.h
*
* Support for the IIC peripheral on IBM PPC 4xx
*
* Copyright (c) 2003 Zultys Technologies.
* Eugene Surovegin <[email protected]> or <[email protected]> *
* Based on original work by
* Ian DaSilva <[email protected]>
* Armin Kuster <[email protected]>
* Matt Porter <[email protected]>
*
* Copyright 2000-2003 MontaVista Software Inc.
*
* 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.
*
*/
#ifndef __I2C_IBM_IIC_H_
#define __I2C_IBM_IIC_H_
\
#include <linux/config.h>
#include <linux/i2c.h>
\

struct iic_regs {
	u16 mdbuf;
	u16 sbbuf;
	u8 lmadr;
	u8 hmadr;
	u8 cntl;
	u8 mdcntl;
	u8 sts;
	u8 extsts;
	u8 lsadr;
	u8 hsadr;
	u8 clkdiv;
	u8 intmsk;
	u8 xfrcnt;
	u8 xtcntlss;
	u8 directcntl;
I47 9
struct ibm_iic_private {
	struct i2c_adapter adap;
	volatile struct iic_regs *vaddr;
	wait_queue_head_t wq;
	int idx;
	int irq;
	int fast_mode;
	u8  clckdiv;
};

D49 2
I50 64
/* IICx_CNTL register */
#define CNTL_HMT 0x80
#define CNTL_AMD 0x40
#define CNTL_TCT_MASK 0x30
#define CNTL_TCT_SHIFT 4
#define CNTL_RPST 0x08
#define CNTL_CHT 0x04
#define CNTL_RW 0x02
#define CNTL_PT 0x01
\
/* IICx_MDCNTL register */
#define MDCNTL_FSDB 0x80
#define MDCNTL_FMDB 0x40
#define MDCNTL_EGC 0x20
#define MDCNTL_FSM 0x10
#define MDCNTL_ESM 0x08
#define MDCNTL_EINT 0x04
#define MDCNTL_EUBS 0x02
#define MDCNTL_HSCL 0x01
\
/* IICx_STS register */
#define STS_SSS 0x80
#define STS_SLPR 0x40
#define STS_MDBS 0x20
#define STS_MDBF 0x10
#define STS_SCMP 0x08
#define STS_ERR 0x04
#define STS_IRQA 0x02
#define STS_PT 0x01
\
/* IICx_EXTSTS register */
#define EXTSTS_IRQP 0x80
#define EXTSTS_BCS_MASK 0x70
#define EXTSTS_BCS_FREE 0x40
#define EXTSTS_IRQD 0x08
#define EXTSTS_LA 0x04
#define EXTSTS_ICT 0x02
#define EXTSTS_XFRA 0x01
\
/* IICx_INTRMSK register */
#define INTRMSK_EIRC 0x80
#define INTRMSK_EIRS 0x40
#define INTRMSK_EIWC 0x20
#define INTRMSK_EIWS 0x10
#define INTRMSK_EIHE 0x08
#define INTRMSK_EIIC 0x04
#define INTRMSK_EITA 0x02
#define INTRMSK_EIMTC 0x01
\
/* IICx_XFRCNT register */
#define XFRCNT_MTC_MASK 0x07
\
/* IICx_XTCNTLSS register */
#define XTCNTLSS_SRC 0x80
#define XTCNTLSS_SRS 0x40
#define XTCNTLSS_SWC 0x20
#define XTCNTLSS_SWS 0x10
#define XTCNTLSS_SRST 0x01
\
/* IICx_DIRECTCNTL register */
#define DIRCNTL_SDAC 0x08
#define DIRCNTL_SCC 0x04
#define DIRCNTL_MSDA 0x02
#define DIRCNTL_MSC 0x01
D52 2
I53 2
/* Check if we really control the I2C bus and bus is free */
#define DIRCTNL_FREE(v) (((v) & 0x0f) = 0x0f)
D55 1
I55 1
#endif /* __I2C_IBM_IIC_H_ */

= drivers/i2c/Makefile = [email protected]|drivers/i2c/Makefile|20020205174018|59980|699ee8af74f52ec9 [email protected][greg]|drivers/i2c/Makefile|20030623222422|55080
D 1.13 03/09/12 12:30:34-07:00 [email protected] +1 -0
B [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 C
c Update PPC4xx I2C driver name
K 58226
O -rw-rw-r--
P drivers/i2c/Makefile
------------------------------------------------

I18 1
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o

= drivers/i2c/Kconfig = [email protected][torvalds]|drivers/i2c/Kconfig|20021030043228|25271|93781e6749f2f6e9 [email protected][torvalds]|drivers/i2c/Kconfig|20030902162248|55767
D 1.15 03/09/12 12:30:34-07:00 [email protected] +2 -6
B [email protected]|ChangeSet|20020205173056|16047|c1d11a41ed024864 C
c Update PPC4xx I2C driver name
K 46908
O -rw-rw-r--
P drivers/i2c/Kconfig
------------------------------------------------

D206 2
I207 2
config I2C_IBM_IIC
tristate "IBM IIC I2C"
D209 4

# Patch checksumë4878fa

#1 lore raw

PATCH 1/1 [2.6] New PPC4xx I2C driver

Quoted 4 lines · Greg KH

Can you please send me a plain-text patch that I can apply to any bk repository?

bk sendpatch is not nice :)

No problem. :)

drivers/i2c/Kconfig +2 -6
diff -Nru a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
@@ -203,13 +203,9 @@
 	tristate "Embedded Planet RPX Lite/Classic suppoort"
 	depends on (RPXLITE || RPXCLASSIC) && I2C_ALGO8XX
 
-config I2C_IBM_OCP_ALGO
-	tristate "IBM on-chip I2C Algorithm"
+config I2C_IBM_IIC
+	tristate "IBM IIC I2C"
 	depends on IBM_OCP && I2C
-
-config I2C_IBM_OCP_ADAP
-	tristate "IBM on-chip I2C Adapter"
-	depends on I2C_IBM_OCP_ALGO
 
 config I2C_IOP3XX
 	tristate "Intel XScale IOP3xx on-chip I2C interface"
drivers/i2c/Makefile +1 -0
diff -Nru a/drivers/i2c/Makefile b/drivers/i2c/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_ITE_I2C_ADAP)	+= i2c-adap-ite.o
 obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
+obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
 obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-y				+= busses/ chips/
drivers/i2c/i2c-algo-ibm_ocp.c deleted +0 -900

900 lines not on this page · raw message

drivers/i2c/i2c-algo-ibm_ocp.h deleted +0 -55

55 lines not on this page · raw message

drivers/i2c/i2c-ibm_iic.c new file +728 -0

728 lines not on this page · raw message

drivers/i2c/i2c-ibm_iic.h new file +124 -0

124 lines not on this page · raw message

#2 lore raw

PATCH 1/1 [2.6] New PPC4xx I2C driver

In reply to Matt Porter
Quoted 4 lines · Matt Porter

This updates the current 2.6 PPC 4xx driver to the rewritten version we have in the PPC development tree. It is cleaner, has less bugs, and has more features. Please apply.

Quoted 8 lines

-Matt

This BitKeeper patch contains the following changesets:
1.1316

# This is a BitKeeper patch. What follows are the unified diffs for the

# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.

Can you please send me a plain-text patch that I can apply to any bk repository?

bk sendpatch is not nice :)

thanks,

greg k-h

#3 lore raw

PATCH 1/1 [2.6] New PPC4xx I2C driver

In reply to Matt Porter
Quoted 7 lines · Matt Porter
Quoted 4 lines · Greg KH

Can you please send me a plain-text patch that I can apply to any bk repository?

bk sendpatch is not nice :)

No problem. :)

Much nicer, thanks. I'll apply this next week and send it off with some other 2.6 i2c updates that I have in my tree.

greg k-h

#4 lore raw

PATCH 1/1 [2.6] New PPC4xx I2C driver

In reply to Matt Porter
Quoted 4 lines

This updates the current 2.6 PPC 4xx driver to the rewritten version we have in the PPC development tree. It is cleaner, has less bugs, and has more features. Please apply.

Hm, we also have a copy of that driver in our I2C CVS repository (intended to be used with 2.4 kernels). If you want us to update is as well, please provide a patch against current CVS.

Signature · 2 lines
Jean Delvare
http://www.ensicaen.ismra.fr/~delvare/
#5 lore raw

PATCH 1/1 [2.6] New PPC4xx I2C driver

In reply to Matt Porter
Quoted 7 lines · Matt Porter
Quoted 4 lines · Greg KH

Can you please send me a plain-text patch that I can apply to any bk repository?

bk sendpatch is not nice :)

No problem. :)

Thanks, I've applied this to my trees and will send it off to Linus when he gets back.

greg k-h