⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c-algo-bit.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * 0 chip did not answer * -x transmission error */static int try_address(struct i2c_adapter *i2c_adap,		       unsigned char addr, int retries){	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;	int i,ret = -1;	for (i=0;i<=retries;i++) {		ret = i2c_outb(i2c_adap,addr);		if (ret == 1 || i == retries)			break;		bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");		i2c_stop(adap);		udelay(adap->udelay);		yield();		bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");		i2c_start(adap);	}	if (i && ret)		bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "			"0x%02x: %s\n", i + 1,			addr & 1 ? "read from" : "write to", addr >> 1,			ret == 1 ? "success" : "failed, timeout?");	return ret;}static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg){	const unsigned char *temp = msg->buf;	int count = msg->len;	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 	int retval;	int wrcount=0;	while (count > 0) {		retval = i2c_outb(i2c_adap, *temp);		if ((retval>0) || (nak_ok && (retval==0)))  { /* ok or ignored NAK */			count--; 			temp++;			wrcount++;		} else { /* arbitration or no acknowledge */			dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");			return (retval<0)? retval : -EFAULT;			        /* got a better one ?? */		}	}	return wrcount;}static int acknak(struct i2c_adapter *i2c_adap, int is_ack){	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;	/* assert: sda is high */	if (is_ack)		/* send ack */		setsda(adap, 0);	udelay((adap->udelay + 1) / 2);	if (sclhi(adap) < 0) {	/* timeout */		dev_err(&i2c_adap->dev, "readbytes: ack/nak timeout\n");		return -ETIMEDOUT;	}	scllo(adap);	return 0;}static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg){	int inval;	int rdcount=0;   	/* counts bytes read */	unsigned char *temp = msg->buf;	int count = msg->len;	const unsigned flags = msg->flags;	while (count > 0) {		inval = i2c_inb(i2c_adap);		if (inval>=0) {			*temp = inval;			rdcount++;		} else {   /* read timed out */			break;		}		temp++;		count--;		/* Some SMBus transactions require that we receive the		   transaction length as the first read byte. */		if (rdcount == 1 && (flags & I2C_M_RECV_LEN)) {			if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {				if (!(flags & I2C_M_NO_RD_ACK))					acknak(i2c_adap, 0);				dev_err(&i2c_adap->dev, "readbytes: invalid "					"block length (%d)\n", inval);				return -EREMOTEIO;			}			/* The original count value accounts for the extra			   bytes, that is, either 1 for a regular transaction,			   or 2 for a PEC transaction. */			count += inval;			msg->len += inval;		}		bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n",			inval,			(flags & I2C_M_NO_RD_ACK)				? "(no ack/nak)"				: (count ? "A" : "NA"));		if (!(flags & I2C_M_NO_RD_ACK)) {			inval = acknak(i2c_adap, count);			if (inval < 0)				return inval;		}	}	return rdcount;}/* doAddress initiates the transfer by generating the start condition (in * try_address) and transmits the address in the necessary format to handle * reads, writes as well as 10bit-addresses. * returns: *  0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set * -x an error occurred (like: -EREMOTEIO if the device did not answer, or *	-ETIMEDOUT, for example if the lines are stuck...)  */static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg){	unsigned short flags = msg->flags;	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;	unsigned char addr;	int ret, retries;	retries = nak_ok ? 0 : i2c_adap->retries;		if ( (flags & I2C_M_TEN)  ) { 		/* a ten bit address */		addr = 0xf0 | (( msg->addr >> 7) & 0x03);		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);		/* try extended address code...*/		ret = try_address(i2c_adap, addr, retries);		if ((ret != 1) && !nak_ok)  {			dev_err(&i2c_adap->dev,				"died at extended address code\n");			return -EREMOTEIO;		}		/* the remaining 8 bit address */		ret = i2c_outb(i2c_adap,msg->addr & 0x7f);		if ((ret != 1) && !nak_ok) {			/* the chip did not ack / xmission error occurred */			dev_err(&i2c_adap->dev, "died at 2nd address code\n");			return -EREMOTEIO;		}		if ( flags & I2C_M_RD ) {			bit_dbg(3, &i2c_adap->dev, "emitting repeated "				"start condition\n");			i2c_repstart(adap);			/* okay, now switch into reading mode */			addr |= 0x01;			ret = try_address(i2c_adap, addr, retries);			if ((ret!=1) && !nak_ok) {				dev_err(&i2c_adap->dev,					"died at repeated address code\n");				return -EREMOTEIO;			}		}	} else {		/* normal 7bit address	*/		addr = ( msg->addr << 1 );		if (flags & I2C_M_RD )			addr |= 1;		if (flags & I2C_M_REV_DIR_ADDR )			addr ^= 1;		ret = try_address(i2c_adap, addr, retries);		if ((ret!=1) && !nak_ok)			return -EREMOTEIO;	}	return 0;}static int bit_xfer(struct i2c_adapter *i2c_adap,		    struct i2c_msg msgs[], int num){	struct i2c_msg *pmsg;	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;		int i,ret;	unsigned short nak_ok;	bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");	i2c_start(adap);	for (i=0;i<num;i++) {		pmsg = &msgs[i];		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 		if (!(pmsg->flags & I2C_M_NOSTART)) {			if (i) {				bit_dbg(3, &i2c_adap->dev, "emitting "					"repeated start condition\n");				i2c_repstart(adap);			}			ret = bit_doAddress(i2c_adap, pmsg);			if ((ret != 0) && !nak_ok) {				bit_dbg(1, &i2c_adap->dev, "NAK from "					"device addr 0x%02x msg #%d\n",					msgs[i].addr, i);				goto bailout;			}		}		if (pmsg->flags & I2C_M_RD ) {			/* read bytes into buffer*/			ret = readbytes(i2c_adap, pmsg);			if (ret >= 1)				bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",					ret, ret == 1 ? "" : "s");			if (ret < pmsg->len) {				if (ret >= 0)					ret = -EREMOTEIO;				goto bailout;			}		} else {			/* write bytes from buffer */			ret = sendbytes(i2c_adap, pmsg);			if (ret >= 1)				bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",					ret, ret == 1 ? "" : "s");			if (ret < pmsg->len) {				if (ret >= 0)					ret = -EREMOTEIO;				goto bailout;			}		}	}	ret = i;bailout:	bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");	i2c_stop(adap);	return ret;}static u32 bit_func(struct i2c_adapter *adap){	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;}/* -----exported algorithm data: -------------------------------------	*/static const struct i2c_algorithm i2c_bit_algo = {	.master_xfer	= bit_xfer,	.functionality	= bit_func,};/*  * registering functions to load algorithms at runtime  */static int i2c_bit_prepare_bus(struct i2c_adapter *adap){	struct i2c_algo_bit_data *bit_adap = adap->algo_data;	if (bit_test) {		int ret = test_bus(bit_adap, adap->name);		if (ret<0)			return -ENODEV;	}	/* register new adapter to i2c module... */	adap->algo = &i2c_bit_algo;	adap->timeout = 100;	/* default values, should	*/	adap->retries = 3;	/* be replaced by defines	*/	return 0;}int i2c_bit_add_bus(struct i2c_adapter *adap){	int err;	err = i2c_bit_prepare_bus(adap);	if (err)		return err;	return i2c_add_adapter(adap);}EXPORT_SYMBOL(i2c_bit_add_bus);int i2c_bit_add_numbered_bus(struct i2c_adapter *adap){	int err;	err = i2c_bit_prepare_bus(adap);	if (err)		return err;	return i2c_add_numbered_adapter(adap);}EXPORT_SYMBOL(i2c_bit_add_numbered_bus);MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -