/* ------------------------------------------------------------------------- i2c-algo-ibm_ocp.c i2c driver algorithms for IBM PPC 405 adapters ------------------------------------------------------------------------- Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com or source@mvista.com 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 and Frodo Looijaard ,and also from Martin Bailey 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 akuster@mvista.com 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 #include #include #include #include #include #include #include #include #include #include #include "i2c-algo-ibm_ocp.h" //ACC#include #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif /* ----- 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 /* debugging - slow down transfer to have a look at the data .. */ /* I use this with two leds&resistors, each one connected to sda,scl */ /* respectively. This makes sure that the algorithm works. Some chips */ /* might not like this, as they have an internal timeout of some mils */ /* #define SLO_IO jif=jiffies;while(time_before_eq(jiffies,jif+i2c_table[minor].veryslow))\ if (need_resched) schedule(); */ /* ----- global variables --------------------------------------------- */ #ifdef SLO_IO int jif; #endif /* module parameters: */ static int i2c_debug=0; static int iic_scan=0; /* have a look at what's hanging 'round */ /* --- 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 #define IIC_SINGLE_XFER 0 #define IIC_COMBINED_XFER 1 #define IIC_ERR_LOST_ARB -2 #define IIC_ERR_INCOMPLETE_XFR -3 #define IIC_ERR_NACK -1 /* --- other auxiliary functions -------------------------------------- */ // // Description: Puts this process to sleep for a period equal to timeout // static inline void iic_sleep(unsigned long timeout) { schedule_timeout( timeout * HZ); } // // 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) { 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); /* 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); /* Set mode control (flush master data buf, enable hold SCL, exit */ /* unknown state. */ iic_outb(adap,iic->mdcntl, 0x47); /* Clear control register */ iic_outb(adap,iic->cntl, 0x0); DEB2(printk(KERN_DEBUG "iic_init: Initialized IIC on PPC 405\n")); return 0; } // // 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) { 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 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); } else return(0); } //------------------------------------ // 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; } // // 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; imdbuf, 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; imdbuf, 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; iIssued 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; imdbuf); // 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)); } } 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 { DEB2(printk("i2c-algo-ppc405.o: wrote %d bytes.\n",ret)); } } } return num; } // // 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; } } } 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; } // // 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; } // // 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)); } else if (cmd == IICO_I2C_LINEREAD) { ret = lines; } return ret; } static u32 iic_func(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; } /* -----exported algorithm data: ------------------------------------- */ static struct i2c_algorithm iic_algo = { "IBM on-chip IIC algorithm", I2C_ALGO_OCP, iic_xfer, NULL, NULL, /* slave_xmit */ NULL, /* slave_recv */ algo_control, /* ioctl */ iic_func, /* functionality */ }; /* * registering functions to load algorithms at runtime */ // // Description: Register bus structure // int i2c_ocp_add_bus(struct i2c_adapter *adap) { struct i2c_algo_iic_data *iic_adap = adap->algo_data; DEB2(printk(KERN_DEBUG "i2c-algo-iic.o: hw routines for %s registered.\n", adap->name)); /* register new adapter to i2c module... */ adap->id |= iic_algo.id; adap->algo = &iic_algo; adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */ #ifdef MODULE MOD_INC_USE_COUNT; #endif iic_init(iic_adap); i2c_add_adapter(adap); /* scan bus */ /* By default scanning the bus is turned off. */ if (iic_scan) { printk(KERN_INFO " i2c-algo-iic.o: scanning bus %s.\n", adap->name); } return 0; } // // Done // int i2c_ocp_del_bus(struct i2c_adapter *adap) { int res; if ((res = i2c_del_adapter(adap)) < 0) return res; DEB2(printk(KERN_DEBUG "i2c-algo-iic.o: adapter unregistered: %s\n",adap->name)); #ifdef MODULE MOD_DEC_USE_COUNT; #endif return 0; } // // Done // int __init i2c_algo_iic_init (void) { printk(KERN_INFO "IBM On-chip iic (i2c) algorithm module 2002.27.03\n"); return 0; } void i2c_algo_iic_exit(void) { return; } EXPORT_SYMBOL(i2c_ocp_add_bus); EXPORT_SYMBOL(i2c_ocp_del_bus); // // The MODULE_* macros resolve to nothing if MODULES is not defined // when this file is compiled. // MODULE_AUTHOR("MontaVista Software "); MODULE_DESCRIPTION("PPC 405 iic algorithm"); MODULE_PARM(iic_test, "i"); MODULE_PARM(iic_scan, "i"); MODULE_PARM(i2c_debug,"i"); MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available"); MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus"); MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); module_init(i2c_algo_iic_init); module_exit(i2c_algo_iic_exit);