xref: /linux/drivers/i2c/algos/i2c-algo-pcf.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20c168cebSRoel Kluin /*
30c168cebSRoel Kluin  * i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters
40c168cebSRoel Kluin  *
50c168cebSRoel Kluin  *   Copyright (C) 1995-1997 Simon G. Vogl
60c168cebSRoel Kluin  *		   1998-2000 Hans Berglund
70c168cebSRoel Kluin  *
80c168cebSRoel Kluin  * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
90c168cebSRoel Kluin  * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey
100c168cebSRoel Kluin  * <mbailey@littlefeet-inc.com>
110c168cebSRoel Kluin  *
120c168cebSRoel Kluin  * Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple
130c168cebSRoel Kluin  * messages, proper stop/repstart signaling during receive, added detect code
140c168cebSRoel Kluin  */
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <linux/kernel.h>
171da177e4SLinus Torvalds #include <linux/module.h>
181da177e4SLinus Torvalds #include <linux/delay.h>
191da177e4SLinus Torvalds #include <linux/errno.h>
201da177e4SLinus Torvalds #include <linux/i2c.h>
211da177e4SLinus Torvalds #include <linux/i2c-algo-pcf.h>
221da177e4SLinus Torvalds #include "i2c-algo-pcf.h"
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #define DEB2(x) if (i2c_debug >= 2) x
261da177e4SLinus Torvalds #define DEB3(x) if (i2c_debug >= 3) x /* print several statistical values */
271da177e4SLinus Torvalds #define DEBPROTO(x) if (i2c_debug >= 9) x;
281da177e4SLinus Torvalds 	/* debug the protocol by showing transferred bits */
291da177e4SLinus Torvalds #define DEF_TIMEOUT 16
301da177e4SLinus Torvalds 
310c168cebSRoel Kluin /*
320c168cebSRoel Kluin  * module parameters:
331da177e4SLinus Torvalds  */
341da177e4SLinus Torvalds static int i2c_debug;
351da177e4SLinus Torvalds 
360c168cebSRoel Kluin /* setting states on the bus with the right timing: */
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds #define set_pcf(adap, ctl, val) adap->setpcf(adap->data, ctl, val)
391da177e4SLinus Torvalds #define get_pcf(adap, ctl) adap->getpcf(adap->data, ctl)
401da177e4SLinus Torvalds #define get_own(adap) adap->getown(adap->data)
411da177e4SLinus Torvalds #define get_clock(adap) adap->getclock(adap->data)
421da177e4SLinus Torvalds #define i2c_outb(adap, val) adap->setpcf(adap->data, 0, val)
431da177e4SLinus Torvalds #define i2c_inb(adap) adap->getpcf(adap->data, 0)
441da177e4SLinus Torvalds 
450c168cebSRoel Kluin /* other auxiliary functions */
461da177e4SLinus Torvalds 
i2c_start(struct i2c_algo_pcf_data * adap)471da177e4SLinus Torvalds static void i2c_start(struct i2c_algo_pcf_data *adap)
481da177e4SLinus Torvalds {
49154d22b0SFrank Seidel 	DEBPROTO(printk(KERN_DEBUG "S "));
501da177e4SLinus Torvalds 	set_pcf(adap, 1, I2C_PCF_START);
511da177e4SLinus Torvalds }
521da177e4SLinus Torvalds 
i2c_repstart(struct i2c_algo_pcf_data * adap)531da177e4SLinus Torvalds static void i2c_repstart(struct i2c_algo_pcf_data *adap)
541da177e4SLinus Torvalds {
551da177e4SLinus Torvalds 	DEBPROTO(printk(" Sr "));
561da177e4SLinus Torvalds 	set_pcf(adap, 1, I2C_PCF_REPSTART);
571da177e4SLinus Torvalds }
581da177e4SLinus Torvalds 
i2c_stop(struct i2c_algo_pcf_data * adap)591da177e4SLinus Torvalds static void i2c_stop(struct i2c_algo_pcf_data *adap)
601da177e4SLinus Torvalds {
611da177e4SLinus Torvalds 	DEBPROTO(printk("P\n"));
621da177e4SLinus Torvalds 	set_pcf(adap, 1, I2C_PCF_STOP);
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds 
handle_lab(struct i2c_algo_pcf_data * adap,const int * status)650573d11bSEric Brower static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
660573d11bSEric Brower {
670573d11bSEric Brower 	DEB2(printk(KERN_INFO
680573d11bSEric Brower 		"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
690573d11bSEric Brower 		*status));
700c168cebSRoel Kluin 	/*
710c168cebSRoel Kluin 	 * Cleanup from LAB -- reset and enable ESO.
720573d11bSEric Brower 	 * This resets the PCF8584; since we've lost the bus, no
730573d11bSEric Brower 	 * further attempts should be made by callers to clean up
740573d11bSEric Brower 	 * (no i2c_stop() etc.)
750573d11bSEric Brower 	 */
760573d11bSEric Brower 	set_pcf(adap, 1, I2C_PCF_PIN);
770573d11bSEric Brower 	set_pcf(adap, 1, I2C_PCF_ESO);
780c168cebSRoel Kluin 	/*
790c168cebSRoel Kluin 	 * We pause for a time period sufficient for any running
800573d11bSEric Brower 	 * I2C transaction to complete -- the arbitration logic won't
810573d11bSEric Brower 	 * work properly until the next START is seen.
820573d11bSEric Brower 	 * It is assumed the bus driver or client has set a proper value.
830573d11bSEric Brower 	 *
840573d11bSEric Brower 	 * REVISIT: should probably use msleep instead of mdelay if we
850573d11bSEric Brower 	 * know we can sleep.
860573d11bSEric Brower 	 */
870573d11bSEric Brower 	if (adap->lab_mdelay)
880573d11bSEric Brower 		mdelay(adap->lab_mdelay);
890573d11bSEric Brower 
900573d11bSEric Brower 	DEB2(printk(KERN_INFO
910573d11bSEric Brower 		"i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
920573d11bSEric Brower 		get_pcf(adap, 1)));
930573d11bSEric Brower }
940573d11bSEric Brower 
wait_for_bb(struct i2c_algo_pcf_data * adap)950c168cebSRoel Kluin static int wait_for_bb(struct i2c_algo_pcf_data *adap)
960c168cebSRoel Kluin {
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds 	int timeout = DEF_TIMEOUT;
991da177e4SLinus Torvalds 	int status;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	status = get_pcf(adap, 1);
1020c168cebSRoel Kluin 
10394d78e18SRoel Kluin 	while (!(status & I2C_PCF_BB) && --timeout) {
1041da177e4SLinus Torvalds 		udelay(100); /* wait for 100 us */
1051da177e4SLinus Torvalds 		status = get_pcf(adap, 1);
1061da177e4SLinus Torvalds 	}
1070c168cebSRoel Kluin 
10894d78e18SRoel Kluin 	if (timeout == 0) {
1091da177e4SLinus Torvalds 		printk(KERN_ERR "Timeout waiting for Bus Busy\n");
11094d78e18SRoel Kluin 		return -ETIMEDOUT;
11194d78e18SRoel Kluin 	}
1120c168cebSRoel Kluin 
11394d78e18SRoel Kluin 	return 0;
1141da177e4SLinus Torvalds }
1151da177e4SLinus Torvalds 
wait_for_pin(struct i2c_algo_pcf_data * adap,int * status)1160c168cebSRoel Kluin static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status)
1170c168cebSRoel Kluin {
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds 	int timeout = DEF_TIMEOUT;
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds 	*status = get_pcf(adap, 1);
1220c168cebSRoel Kluin 
12394d78e18SRoel Kluin 	while ((*status & I2C_PCF_PIN) && --timeout) {
12408e5338dSDavid Miller 		adap->waitforpin(adap->data);
1251da177e4SLinus Torvalds 		*status = get_pcf(adap, 1);
1261da177e4SLinus Torvalds 	}
1271da177e4SLinus Torvalds 	if (*status & I2C_PCF_LAB) {
1280573d11bSEric Brower 		handle_lab(adap, status);
1290c168cebSRoel Kluin 		return -EINTR;
1301da177e4SLinus Torvalds 	}
1310c168cebSRoel Kluin 
13294d78e18SRoel Kluin 	if (timeout == 0)
13394d78e18SRoel Kluin 		return -ETIMEDOUT;
13494d78e18SRoel Kluin 
1350c168cebSRoel Kluin 	return 0;
1361da177e4SLinus Torvalds }
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds /*
1391da177e4SLinus Torvalds  * This should perform the 'PCF8584 initialization sequence' as described
1401da177e4SLinus Torvalds  * in the Philips IC12 data book (1995, Aug 29).
1411da177e4SLinus Torvalds  * There should be a 30 clock cycle wait after reset, I assume this
1421da177e4SLinus Torvalds  * has been fulfilled.
1431da177e4SLinus Torvalds  * There should be a delay at the end equal to the longest I2C message
1441da177e4SLinus Torvalds  * to synchronize the BB-bit (in multimaster systems). How long is
1451da177e4SLinus Torvalds  * this? I assume 1 second is always long enough.
1461da177e4SLinus Torvalds  *
1471da177e4SLinus Torvalds  * vdovikin: added detect code for PCF8584
1481da177e4SLinus Torvalds  */
pcf_init_8584(struct i2c_algo_pcf_data * adap)1491da177e4SLinus Torvalds static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
1501da177e4SLinus Torvalds {
1511da177e4SLinus Torvalds 	unsigned char temp;
1521da177e4SLinus Torvalds 
1530c168cebSRoel Kluin 	DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n",
1540c168cebSRoel Kluin 				get_pcf(adap, 1)));
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds 	/* S1=0x80: S0 selected, serial interface off */
1571da177e4SLinus Torvalds 	set_pcf(adap, 1, I2C_PCF_PIN);
1580c168cebSRoel Kluin 	/*
1590c168cebSRoel Kluin 	 * check to see S1 now used as R/W ctrl -
1600c168cebSRoel Kluin 	 * PCF8584 does that when ESO is zero
1610c168cebSRoel Kluin 	 */
1621da177e4SLinus Torvalds 	if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) {
1631da177e4SLinus Torvalds 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp));
1647d9b48eaSUwe Kleine-König 		return -ENXIO; /* definitely not PCF8584 */
1651da177e4SLinus Torvalds 	}
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	/* load own address in S0, effective address is (own << 1) */
1681da177e4SLinus Torvalds 	i2c_outb(adap, get_own(adap));
1691da177e4SLinus Torvalds 	/* check it's really written */
1701da177e4SLinus Torvalds 	if ((temp = i2c_inb(adap)) != get_own(adap)) {
1711da177e4SLinus Torvalds 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp));
1721da177e4SLinus Torvalds 		return -ENXIO;
1731da177e4SLinus Torvalds 	}
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds 	/* S1=0xA0, next byte in S2 */
1761da177e4SLinus Torvalds 	set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1);
1771da177e4SLinus Torvalds 	/* check to see S2 now selected */
1781da177e4SLinus Torvalds 	if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) {
1791da177e4SLinus Torvalds 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S2 (0x%02x).\n", temp));
1801da177e4SLinus Torvalds 		return -ENXIO;
1811da177e4SLinus Torvalds 	}
1821da177e4SLinus Torvalds 
1831da177e4SLinus Torvalds 	/* load clock register S2 */
1841da177e4SLinus Torvalds 	i2c_outb(adap, get_clock(adap));
1851da177e4SLinus Torvalds 	/* check it's really written, the only 5 lowest bits does matter */
1861da177e4SLinus Torvalds 	if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) {
1871da177e4SLinus Torvalds 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp));
1881da177e4SLinus Torvalds 		return -ENXIO;
1891da177e4SLinus Torvalds 	}
1901da177e4SLinus Torvalds 
1911da177e4SLinus Torvalds 	/* Enable serial interface, idle, S0 selected */
1921da177e4SLinus Torvalds 	set_pcf(adap, 1, I2C_PCF_IDLE);
1931da177e4SLinus Torvalds 
1941da177e4SLinus Torvalds 	/* check to see PCF is really idled and we can access status register */
1951da177e4SLinus Torvalds 	if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) {
1961da177e4SLinus Torvalds 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp));
1971da177e4SLinus Torvalds 		return -ENXIO;
1981da177e4SLinus Torvalds 	}
1991da177e4SLinus Torvalds 
200a672b4c1SDavid Miller 	printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n");
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds 	return 0;
2031da177e4SLinus Torvalds }
2041da177e4SLinus Torvalds 
pcf_sendbytes(struct i2c_adapter * i2c_adap,const char * buf,int count,int last)2051da177e4SLinus Torvalds static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
2061da177e4SLinus Torvalds 			 int count, int last)
2071da177e4SLinus Torvalds {
2081da177e4SLinus Torvalds 	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
2091da177e4SLinus Torvalds 	int wrcount, status, timeout;
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds 	for (wrcount=0; wrcount<count; ++wrcount) {
2121da177e4SLinus Torvalds 		DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n",
2131da177e4SLinus Torvalds 				buf[wrcount] & 0xff));
2141da177e4SLinus Torvalds 		i2c_outb(adap, buf[wrcount]);
2151da177e4SLinus Torvalds 		timeout = wait_for_pin(adap, &status);
2161da177e4SLinus Torvalds 		if (timeout) {
2170c168cebSRoel Kluin 			if (timeout == -EINTR)
2180c168cebSRoel Kluin 				return -EINTR; /* arbitration lost */
2190c168cebSRoel Kluin 
2201da177e4SLinus Torvalds 			i2c_stop(adap);
2211da177e4SLinus Torvalds 			dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n");
2221da177e4SLinus Torvalds 			return -EREMOTEIO; /* got a better one ?? */
2231da177e4SLinus Torvalds 		}
2241da177e4SLinus Torvalds 		if (status & I2C_PCF_LRB) {
2251da177e4SLinus Torvalds 			i2c_stop(adap);
2261da177e4SLinus Torvalds 			dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n");
2271da177e4SLinus Torvalds 			return -EREMOTEIO; /* got a better one ?? */
2281da177e4SLinus Torvalds 		}
2291da177e4SLinus Torvalds 	}
2300c168cebSRoel Kluin 	if (last)
2311da177e4SLinus Torvalds 		i2c_stop(adap);
2320c168cebSRoel Kluin 	else
2331da177e4SLinus Torvalds 		i2c_repstart(adap);
2341da177e4SLinus Torvalds 
2350c168cebSRoel Kluin 	return wrcount;
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
pcf_readbytes(struct i2c_adapter * i2c_adap,char * buf,int count,int last)2381da177e4SLinus Torvalds static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
2391da177e4SLinus Torvalds 			 int count, int last)
2401da177e4SLinus Torvalds {
2411da177e4SLinus Torvalds 	int i, status;
2421da177e4SLinus Torvalds 	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
2431da177e4SLinus Torvalds 	int wfp;
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds 	/* increment number of bytes to read by one -- read dummy byte */
2461da177e4SLinus Torvalds 	for (i = 0; i <= count; i++) {
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds 		if ((wfp = wait_for_pin(adap, &status))) {
2490c168cebSRoel Kluin 			if (wfp == -EINTR)
2500c168cebSRoel Kluin 				return -EINTR; /* arbitration lost */
2510c168cebSRoel Kluin 
2521da177e4SLinus Torvalds 			i2c_stop(adap);
2531da177e4SLinus Torvalds 			dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n");
2540c168cebSRoel Kluin 			return -1;
2551da177e4SLinus Torvalds 		}
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 		if ((status & I2C_PCF_LRB) && (i != count)) {
2581da177e4SLinus Torvalds 			i2c_stop(adap);
2591da177e4SLinus Torvalds 			dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n");
2600c168cebSRoel Kluin 			return -1;
2611da177e4SLinus Torvalds 		}
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 		if (i == count - 1) {
2641da177e4SLinus Torvalds 			set_pcf(adap, 1, I2C_PCF_ESO);
2650c168cebSRoel Kluin 		} else if (i == count) {
2660c168cebSRoel Kluin 			if (last)
2671da177e4SLinus Torvalds 				i2c_stop(adap);
2680c168cebSRoel Kluin 			else
2691da177e4SLinus Torvalds 				i2c_repstart(adap);
2701da177e4SLinus Torvalds 		}
2711da177e4SLinus Torvalds 
2720c168cebSRoel Kluin 		if (i)
2731da177e4SLinus Torvalds 			buf[i - 1] = i2c_inb(adap);
2740c168cebSRoel Kluin 		else
2751da177e4SLinus Torvalds 			i2c_inb(adap); /* dummy read */
2761da177e4SLinus Torvalds 	}
2771da177e4SLinus Torvalds 
2780c168cebSRoel Kluin 	return i - 1;
2791da177e4SLinus Torvalds }
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 
pcf_doAddress(struct i2c_algo_pcf_data * adap,struct i2c_msg * msg)2826408a833SJean Delvare static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
2836408a833SJean Delvare 			 struct i2c_msg *msg)
2841da177e4SLinus Torvalds {
285ac6d5298SPeter Rosin 	unsigned char addr = i2c_8bit_addr_from_msg(msg);
2866408a833SJean Delvare 
287ac6d5298SPeter Rosin 	if (msg->flags & I2C_M_REV_DIR_ADDR)
2881da177e4SLinus Torvalds 		addr ^= 1;
2891da177e4SLinus Torvalds 	i2c_outb(adap, addr);
2906408a833SJean Delvare 
2911da177e4SLinus Torvalds 	return 0;
2921da177e4SLinus Torvalds }
2931da177e4SLinus Torvalds 
pcf_xfer(struct i2c_adapter * i2c_adap,struct i2c_msg * msgs,int num)2941da177e4SLinus Torvalds static int pcf_xfer(struct i2c_adapter *i2c_adap,
2951da177e4SLinus Torvalds 		    struct i2c_msg *msgs,
2961da177e4SLinus Torvalds 		    int num)
2971da177e4SLinus Torvalds {
2981da177e4SLinus Torvalds 	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
2991da177e4SLinus Torvalds 	struct i2c_msg *pmsg;
3001da177e4SLinus Torvalds 	int i;
3011da177e4SLinus Torvalds 	int ret=0, timeout, status;
3021da177e4SLinus Torvalds 
30330091404SDavid Miller 	if (adap->xfer_begin)
30430091404SDavid Miller 		adap->xfer_begin(adap->data);
3051da177e4SLinus Torvalds 
3061da177e4SLinus Torvalds 	/* Check for bus busy */
3071da177e4SLinus Torvalds 	timeout = wait_for_bb(adap);
3081da177e4SLinus Torvalds 	if (timeout) {
3091da177e4SLinus Torvalds 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: "
3101da177e4SLinus Torvalds 			    "Timeout waiting for BB in pcf_xfer\n");)
31130091404SDavid Miller 		i = -EIO;
31230091404SDavid Miller 		goto out;
3131da177e4SLinus Torvalds 	}
3141da177e4SLinus Torvalds 
3151da177e4SLinus Torvalds 	for (i = 0;ret >= 0 && i < num; i++) {
3161da177e4SLinus Torvalds 		pmsg = &msgs[i];
3171da177e4SLinus Torvalds 
3181da177e4SLinus Torvalds 		DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n",
3191da177e4SLinus Torvalds 		     pmsg->flags & I2C_M_RD ? "read" : "write",
3201da177e4SLinus Torvalds 		     pmsg->len, pmsg->addr, i + 1, num);)
3211da177e4SLinus Torvalds 
3226408a833SJean Delvare 		ret = pcf_doAddress(adap, pmsg);
3231da177e4SLinus Torvalds 
3241da177e4SLinus Torvalds 		/* Send START */
3250c168cebSRoel Kluin 		if (i == 0)
3261da177e4SLinus Torvalds 			i2c_start(adap);
3271da177e4SLinus Torvalds 
3281da177e4SLinus Torvalds 		/* Wait for PIN (pending interrupt NOT) */
3291da177e4SLinus Torvalds 		timeout = wait_for_pin(adap, &status);
3301da177e4SLinus Torvalds 		if (timeout) {
3311da177e4SLinus Torvalds 			if (timeout == -EINTR) {
3321da177e4SLinus Torvalds 				/* arbitration lost */
33330091404SDavid Miller 				i = -EINTR;
33430091404SDavid Miller 				goto out;
3351da177e4SLinus Torvalds 			}
3361da177e4SLinus Torvalds 			i2c_stop(adap);
3371da177e4SLinus Torvalds 			DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting "
3381da177e4SLinus Torvalds 				    "for PIN(1) in pcf_xfer\n");)
33930091404SDavid Miller 			i = -EREMOTEIO;
34030091404SDavid Miller 			goto out;
3411da177e4SLinus Torvalds 		}
3421da177e4SLinus Torvalds 
3431da177e4SLinus Torvalds 		/* Check LRB (last rcvd bit - slave ack) */
3441da177e4SLinus Torvalds 		if (status & I2C_PCF_LRB) {
3451da177e4SLinus Torvalds 			i2c_stop(adap);
3461da177e4SLinus Torvalds 			DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
34730091404SDavid Miller 			i = -EREMOTEIO;
34830091404SDavid Miller 			goto out;
3491da177e4SLinus Torvalds 		}
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds 		DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
3521da177e4SLinus Torvalds 			    i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
3531da177e4SLinus Torvalds 
3541da177e4SLinus Torvalds 		if (pmsg->flags & I2C_M_RD) {
3551da177e4SLinus Torvalds 			ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len,
3561da177e4SLinus Torvalds 					    (i + 1 == num));
3571da177e4SLinus Torvalds 
3581da177e4SLinus Torvalds 			if (ret != pmsg->len) {
3591da177e4SLinus Torvalds 				DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
3601da177e4SLinus Torvalds 					    "only read %d bytes.\n",ret));
3611da177e4SLinus Torvalds 			} else {
3621da177e4SLinus Torvalds 				DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: read %d bytes.\n",ret));
3631da177e4SLinus Torvalds 			}
3640c168cebSRoel Kluin 		} else {
3651da177e4SLinus Torvalds 			ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
3661da177e4SLinus Torvalds 					    (i + 1 == num));
3671da177e4SLinus Torvalds 
3681da177e4SLinus Torvalds 			if (ret != pmsg->len) {
3691da177e4SLinus Torvalds 				DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
3701da177e4SLinus Torvalds 					    "only wrote %d bytes.\n",ret));
3711da177e4SLinus Torvalds 			} else {
3721da177e4SLinus Torvalds 				DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: wrote %d bytes.\n",ret));
3731da177e4SLinus Torvalds 			}
3741da177e4SLinus Torvalds 		}
3751da177e4SLinus Torvalds 	}
3761da177e4SLinus Torvalds 
37730091404SDavid Miller out:
37830091404SDavid Miller 	if (adap->xfer_end)
37930091404SDavid Miller 		adap->xfer_end(adap->data);
3800c168cebSRoel Kluin 	return i;
3811da177e4SLinus Torvalds }
3821da177e4SLinus Torvalds 
pcf_func(struct i2c_adapter * adap)3831da177e4SLinus Torvalds static u32 pcf_func(struct i2c_adapter *adap)
3841da177e4SLinus Torvalds {
3851da177e4SLinus Torvalds 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
3866408a833SJean Delvare 	       I2C_FUNC_PROTOCOL_MANGLING;
3871da177e4SLinus Torvalds }
3881da177e4SLinus Torvalds 
3890c168cebSRoel Kluin /* exported algorithm data: */
3909e11a9fbSJean Delvare static const struct i2c_algorithm pcf_algo = {
3911da177e4SLinus Torvalds 	.master_xfer	= pcf_xfer,
3921da177e4SLinus Torvalds 	.functionality	= pcf_func,
3931da177e4SLinus Torvalds };
3941da177e4SLinus Torvalds 
3951da177e4SLinus Torvalds /*
3961da177e4SLinus Torvalds  * registering functions to load algorithms at runtime
3971da177e4SLinus Torvalds  */
i2c_pcf_add_bus(struct i2c_adapter * adap)3981da177e4SLinus Torvalds int i2c_pcf_add_bus(struct i2c_adapter *adap)
3991da177e4SLinus Torvalds {
4001da177e4SLinus Torvalds 	struct i2c_algo_pcf_data *pcf_adap = adap->algo_data;
4011da177e4SLinus Torvalds 	int rval;
4021da177e4SLinus Torvalds 
4031da177e4SLinus Torvalds 	DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
4041da177e4SLinus Torvalds 
4051da177e4SLinus Torvalds 	/* register new adapter to i2c module... */
4061da177e4SLinus Torvalds 	adap->algo = &pcf_algo;
4071da177e4SLinus Torvalds 
408b39ad0cfSMark M. Hoffman 	if ((rval = pcf_init_8584(pcf_adap)))
409b39ad0cfSMark M. Hoffman 		return rval;
410b39ad0cfSMark M. Hoffman 
411b39ad0cfSMark M. Hoffman 	rval = i2c_add_adapter(adap);
412b39ad0cfSMark M. Hoffman 
4131da177e4SLinus Torvalds 	return rval;
4141da177e4SLinus Torvalds }
4151da177e4SLinus Torvalds EXPORT_SYMBOL(i2c_pcf_add_bus);
4161da177e4SLinus Torvalds 
4171da177e4SLinus Torvalds MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
4181da177e4SLinus Torvalds MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
4191da177e4SLinus Torvalds MODULE_LICENSE("GPL");
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
4221da177e4SLinus Torvalds MODULE_PARM_DESC(i2c_debug,
4231da177e4SLinus Torvalds 	"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
424