162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1995-1997 Simon G. Vogl 662306a36Sopenharmony_ci * 1998-2000 Hans Berglund 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and 962306a36Sopenharmony_ci * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey 1062306a36Sopenharmony_ci * <mbailey@littlefeet-inc.com> 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple 1362306a36Sopenharmony_ci * messages, proper stop/repstart signaling during receive, added detect code 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/kernel.h> 1762306a36Sopenharmony_ci#include <linux/module.h> 1862306a36Sopenharmony_ci#include <linux/delay.h> 1962306a36Sopenharmony_ci#include <linux/errno.h> 2062306a36Sopenharmony_ci#include <linux/i2c.h> 2162306a36Sopenharmony_ci#include <linux/i2c-algo-pcf.h> 2262306a36Sopenharmony_ci#include "i2c-algo-pcf.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define DEB2(x) if (i2c_debug >= 2) x 2662306a36Sopenharmony_ci#define DEB3(x) if (i2c_debug >= 3) x /* print several statistical values */ 2762306a36Sopenharmony_ci#define DEBPROTO(x) if (i2c_debug >= 9) x; 2862306a36Sopenharmony_ci /* debug the protocol by showing transferred bits */ 2962306a36Sopenharmony_ci#define DEF_TIMEOUT 16 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* 3262306a36Sopenharmony_ci * module parameters: 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_cistatic int i2c_debug; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* setting states on the bus with the right timing: */ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define set_pcf(adap, ctl, val) adap->setpcf(adap->data, ctl, val) 3962306a36Sopenharmony_ci#define get_pcf(adap, ctl) adap->getpcf(adap->data, ctl) 4062306a36Sopenharmony_ci#define get_own(adap) adap->getown(adap->data) 4162306a36Sopenharmony_ci#define get_clock(adap) adap->getclock(adap->data) 4262306a36Sopenharmony_ci#define i2c_outb(adap, val) adap->setpcf(adap->data, 0, val) 4362306a36Sopenharmony_ci#define i2c_inb(adap) adap->getpcf(adap->data, 0) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* other auxiliary functions */ 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic void i2c_start(struct i2c_algo_pcf_data *adap) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci DEBPROTO(printk(KERN_DEBUG "S ")); 5062306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_START); 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic void i2c_repstart(struct i2c_algo_pcf_data *adap) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci DEBPROTO(printk(" Sr ")); 5662306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_REPSTART); 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic void i2c_stop(struct i2c_algo_pcf_data *adap) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci DEBPROTO(printk("P\n")); 6262306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_STOP); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic void handle_lab(struct i2c_algo_pcf_data *adap, const int *status) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci DEB2(printk(KERN_INFO 6862306a36Sopenharmony_ci "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", 6962306a36Sopenharmony_ci *status)); 7062306a36Sopenharmony_ci /* 7162306a36Sopenharmony_ci * Cleanup from LAB -- reset and enable ESO. 7262306a36Sopenharmony_ci * This resets the PCF8584; since we've lost the bus, no 7362306a36Sopenharmony_ci * further attempts should be made by callers to clean up 7462306a36Sopenharmony_ci * (no i2c_stop() etc.) 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_PIN); 7762306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_ESO); 7862306a36Sopenharmony_ci /* 7962306a36Sopenharmony_ci * We pause for a time period sufficient for any running 8062306a36Sopenharmony_ci * I2C transaction to complete -- the arbitration logic won't 8162306a36Sopenharmony_ci * work properly until the next START is seen. 8262306a36Sopenharmony_ci * It is assumed the bus driver or client has set a proper value. 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * REVISIT: should probably use msleep instead of mdelay if we 8562306a36Sopenharmony_ci * know we can sleep. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci if (adap->lab_mdelay) 8862306a36Sopenharmony_ci mdelay(adap->lab_mdelay); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci DEB2(printk(KERN_INFO 9162306a36Sopenharmony_ci "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", 9262306a36Sopenharmony_ci get_pcf(adap, 1))); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int wait_for_bb(struct i2c_algo_pcf_data *adap) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci int timeout = DEF_TIMEOUT; 9962306a36Sopenharmony_ci int status; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci status = get_pcf(adap, 1); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci while (!(status & I2C_PCF_BB) && --timeout) { 10462306a36Sopenharmony_ci udelay(100); /* wait for 100 us */ 10562306a36Sopenharmony_ci status = get_pcf(adap, 1); 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (timeout == 0) { 10962306a36Sopenharmony_ci printk(KERN_ERR "Timeout waiting for Bus Busy\n"); 11062306a36Sopenharmony_ci return -ETIMEDOUT; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return 0; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci int timeout = DEF_TIMEOUT; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci *status = get_pcf(adap, 1); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci while ((*status & I2C_PCF_PIN) && --timeout) { 12462306a36Sopenharmony_ci adap->waitforpin(adap->data); 12562306a36Sopenharmony_ci *status = get_pcf(adap, 1); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci if (*status & I2C_PCF_LAB) { 12862306a36Sopenharmony_ci handle_lab(adap, status); 12962306a36Sopenharmony_ci return -EINTR; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (timeout == 0) 13362306a36Sopenharmony_ci return -ETIMEDOUT; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci return 0; 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/* 13962306a36Sopenharmony_ci * This should perform the 'PCF8584 initialization sequence' as described 14062306a36Sopenharmony_ci * in the Philips IC12 data book (1995, Aug 29). 14162306a36Sopenharmony_ci * There should be a 30 clock cycle wait after reset, I assume this 14262306a36Sopenharmony_ci * has been fulfilled. 14362306a36Sopenharmony_ci * There should be a delay at the end equal to the longest I2C message 14462306a36Sopenharmony_ci * to synchronize the BB-bit (in multimaster systems). How long is 14562306a36Sopenharmony_ci * this? I assume 1 second is always long enough. 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * vdovikin: added detect code for PCF8584 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistatic int pcf_init_8584 (struct i2c_algo_pcf_data *adap) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci unsigned char temp; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n", 15462306a36Sopenharmony_ci get_pcf(adap, 1))); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* S1=0x80: S0 selected, serial interface off */ 15762306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_PIN); 15862306a36Sopenharmony_ci /* 15962306a36Sopenharmony_ci * check to see S1 now used as R/W ctrl - 16062306a36Sopenharmony_ci * PCF8584 does that when ESO is zero 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_ci if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) { 16362306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp)); 16462306a36Sopenharmony_ci return -ENXIO; /* definitely not PCF8584 */ 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* load own address in S0, effective address is (own << 1) */ 16862306a36Sopenharmony_ci i2c_outb(adap, get_own(adap)); 16962306a36Sopenharmony_ci /* check it's really written */ 17062306a36Sopenharmony_ci if ((temp = i2c_inb(adap)) != get_own(adap)) { 17162306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp)); 17262306a36Sopenharmony_ci return -ENXIO; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* S1=0xA0, next byte in S2 */ 17662306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1); 17762306a36Sopenharmony_ci /* check to see S2 now selected */ 17862306a36Sopenharmony_ci if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) { 17962306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S2 (0x%02x).\n", temp)); 18062306a36Sopenharmony_ci return -ENXIO; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* load clock register S2 */ 18462306a36Sopenharmony_ci i2c_outb(adap, get_clock(adap)); 18562306a36Sopenharmony_ci /* check it's really written, the only 5 lowest bits does matter */ 18662306a36Sopenharmony_ci if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) { 18762306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp)); 18862306a36Sopenharmony_ci return -ENXIO; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* Enable serial interface, idle, S0 selected */ 19262306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_IDLE); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci /* check to see PCF is really idled and we can access status register */ 19562306a36Sopenharmony_ci if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) { 19662306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp)); 19762306a36Sopenharmony_ci return -ENXIO; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n"); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, 20662306a36Sopenharmony_ci int count, int last) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; 20962306a36Sopenharmony_ci int wrcount, status, timeout; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci for (wrcount=0; wrcount<count; ++wrcount) { 21262306a36Sopenharmony_ci DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n", 21362306a36Sopenharmony_ci buf[wrcount] & 0xff)); 21462306a36Sopenharmony_ci i2c_outb(adap, buf[wrcount]); 21562306a36Sopenharmony_ci timeout = wait_for_pin(adap, &status); 21662306a36Sopenharmony_ci if (timeout) { 21762306a36Sopenharmony_ci if (timeout == -EINTR) 21862306a36Sopenharmony_ci return -EINTR; /* arbitration lost */ 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci i2c_stop(adap); 22162306a36Sopenharmony_ci dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n"); 22262306a36Sopenharmony_ci return -EREMOTEIO; /* got a better one ?? */ 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci if (status & I2C_PCF_LRB) { 22562306a36Sopenharmony_ci i2c_stop(adap); 22662306a36Sopenharmony_ci dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n"); 22762306a36Sopenharmony_ci return -EREMOTEIO; /* got a better one ?? */ 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci if (last) 23162306a36Sopenharmony_ci i2c_stop(adap); 23262306a36Sopenharmony_ci else 23362306a36Sopenharmony_ci i2c_repstart(adap); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return wrcount; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, 23962306a36Sopenharmony_ci int count, int last) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci int i, status; 24262306a36Sopenharmony_ci struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; 24362306a36Sopenharmony_ci int wfp; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* increment number of bytes to read by one -- read dummy byte */ 24662306a36Sopenharmony_ci for (i = 0; i <= count; i++) { 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if ((wfp = wait_for_pin(adap, &status))) { 24962306a36Sopenharmony_ci if (wfp == -EINTR) 25062306a36Sopenharmony_ci return -EINTR; /* arbitration lost */ 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci i2c_stop(adap); 25362306a36Sopenharmony_ci dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n"); 25462306a36Sopenharmony_ci return -1; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if ((status & I2C_PCF_LRB) && (i != count)) { 25862306a36Sopenharmony_ci i2c_stop(adap); 25962306a36Sopenharmony_ci dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n"); 26062306a36Sopenharmony_ci return -1; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (i == count - 1) { 26462306a36Sopenharmony_ci set_pcf(adap, 1, I2C_PCF_ESO); 26562306a36Sopenharmony_ci } else if (i == count) { 26662306a36Sopenharmony_ci if (last) 26762306a36Sopenharmony_ci i2c_stop(adap); 26862306a36Sopenharmony_ci else 26962306a36Sopenharmony_ci i2c_repstart(adap); 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (i) 27362306a36Sopenharmony_ci buf[i - 1] = i2c_inb(adap); 27462306a36Sopenharmony_ci else 27562306a36Sopenharmony_ci i2c_inb(adap); /* dummy read */ 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci return i - 1; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int pcf_doAddress(struct i2c_algo_pcf_data *adap, 28362306a36Sopenharmony_ci struct i2c_msg *msg) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci unsigned char addr = i2c_8bit_addr_from_msg(msg); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (msg->flags & I2C_M_REV_DIR_ADDR) 28862306a36Sopenharmony_ci addr ^= 1; 28962306a36Sopenharmony_ci i2c_outb(adap, addr); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return 0; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic int pcf_xfer(struct i2c_adapter *i2c_adap, 29562306a36Sopenharmony_ci struct i2c_msg *msgs, 29662306a36Sopenharmony_ci int num) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; 29962306a36Sopenharmony_ci struct i2c_msg *pmsg; 30062306a36Sopenharmony_ci int i; 30162306a36Sopenharmony_ci int ret=0, timeout, status; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (adap->xfer_begin) 30462306a36Sopenharmony_ci adap->xfer_begin(adap->data); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* Check for bus busy */ 30762306a36Sopenharmony_ci timeout = wait_for_bb(adap); 30862306a36Sopenharmony_ci if (timeout) { 30962306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: " 31062306a36Sopenharmony_ci "Timeout waiting for BB in pcf_xfer\n");) 31162306a36Sopenharmony_ci i = -EIO; 31262306a36Sopenharmony_ci goto out; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci for (i = 0;ret >= 0 && i < num; i++) { 31662306a36Sopenharmony_ci pmsg = &msgs[i]; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n", 31962306a36Sopenharmony_ci pmsg->flags & I2C_M_RD ? "read" : "write", 32062306a36Sopenharmony_ci pmsg->len, pmsg->addr, i + 1, num);) 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci ret = pcf_doAddress(adap, pmsg); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* Send START */ 32562306a36Sopenharmony_ci if (i == 0) 32662306a36Sopenharmony_ci i2c_start(adap); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci /* Wait for PIN (pending interrupt NOT) */ 32962306a36Sopenharmony_ci timeout = wait_for_pin(adap, &status); 33062306a36Sopenharmony_ci if (timeout) { 33162306a36Sopenharmony_ci if (timeout == -EINTR) { 33262306a36Sopenharmony_ci /* arbitration lost */ 33362306a36Sopenharmony_ci i = -EINTR; 33462306a36Sopenharmony_ci goto out; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci i2c_stop(adap); 33762306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting " 33862306a36Sopenharmony_ci "for PIN(1) in pcf_xfer\n");) 33962306a36Sopenharmony_ci i = -EREMOTEIO; 34062306a36Sopenharmony_ci goto out; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci /* Check LRB (last rcvd bit - slave ack) */ 34462306a36Sopenharmony_ci if (status & I2C_PCF_LRB) { 34562306a36Sopenharmony_ci i2c_stop(adap); 34662306a36Sopenharmony_ci DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");) 34762306a36Sopenharmony_ci i = -EREMOTEIO; 34862306a36Sopenharmony_ci goto out; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", 35262306a36Sopenharmony_ci i, msgs[i].addr, msgs[i].flags, msgs[i].len);) 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (pmsg->flags & I2C_M_RD) { 35562306a36Sopenharmony_ci ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len, 35662306a36Sopenharmony_ci (i + 1 == num)); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if (ret != pmsg->len) { 35962306a36Sopenharmony_ci DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: " 36062306a36Sopenharmony_ci "only read %d bytes.\n",ret)); 36162306a36Sopenharmony_ci } else { 36262306a36Sopenharmony_ci DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: read %d bytes.\n",ret)); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci } else { 36562306a36Sopenharmony_ci ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len, 36662306a36Sopenharmony_ci (i + 1 == num)); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if (ret != pmsg->len) { 36962306a36Sopenharmony_ci DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: " 37062306a36Sopenharmony_ci "only wrote %d bytes.\n",ret)); 37162306a36Sopenharmony_ci } else { 37262306a36Sopenharmony_ci DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: wrote %d bytes.\n",ret)); 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ciout: 37862306a36Sopenharmony_ci if (adap->xfer_end) 37962306a36Sopenharmony_ci adap->xfer_end(adap->data); 38062306a36Sopenharmony_ci return i; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic u32 pcf_func(struct i2c_adapter *adap) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 38662306a36Sopenharmony_ci I2C_FUNC_PROTOCOL_MANGLING; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci/* exported algorithm data: */ 39062306a36Sopenharmony_cistatic const struct i2c_algorithm pcf_algo = { 39162306a36Sopenharmony_ci .master_xfer = pcf_xfer, 39262306a36Sopenharmony_ci .functionality = pcf_func, 39362306a36Sopenharmony_ci}; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci/* 39662306a36Sopenharmony_ci * registering functions to load algorithms at runtime 39762306a36Sopenharmony_ci */ 39862306a36Sopenharmony_ciint i2c_pcf_add_bus(struct i2c_adapter *adap) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci struct i2c_algo_pcf_data *pcf_adap = adap->algo_data; 40162306a36Sopenharmony_ci int rval; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci DEB2(dev_dbg(&adap->dev, "hw routines registered.\n")); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci /* register new adapter to i2c module... */ 40662306a36Sopenharmony_ci adap->algo = &pcf_algo; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if ((rval = pcf_init_8584(pcf_adap))) 40962306a36Sopenharmony_ci return rval; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci rval = i2c_add_adapter(adap); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci return rval; 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ciEXPORT_SYMBOL(i2c_pcf_add_bus); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ciMODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); 41862306a36Sopenharmony_ciMODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); 41962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cimodule_param(i2c_debug, int, S_IRUGO | S_IWUSR); 42262306a36Sopenharmony_ciMODULE_PARM_DESC(i2c_debug, 42362306a36Sopenharmony_ci "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); 424