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

📄 i2c-ali15x3.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		outb_p(ALI15X3_T_OUT, SMBHSTCNT);		temp = inb_p(SMBHSTSTS);	}	/* now check the error bits and the busy bit */	if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {		/* do a clear-on-write */		outb_p(0xFF, SMBHSTSTS);		if ((temp = inb_p(SMBHSTSTS)) &		    (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {			/* this is probably going to be correctable only by a power reset			   as one of the bits now appears to be stuck */			/* This may be a bus or device with electrical problems. */			dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - "				"controller or device on bus is probably hung\n",				temp);			return -1;		}	} else {		/* check and clear done bit */		if (temp & ALI15X3_STS_DONE) {			outb_p(temp, SMBHSTSTS);		}	}	/* start the transaction by writing anything to the start register */	outb_p(0xFF, SMBHSTSTART);	/* We will always wait for a fraction of a second! */	timeout = 0;	do {		msleep(1);		temp = inb_p(SMBHSTSTS);	} while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))		 && (timeout++ < MAX_TIMEOUT));	/* If the SMBus is still busy, we give up */	if (timeout >= MAX_TIMEOUT) {		result = -1;		dev_err(&adap->dev, "SMBus Timeout!\n");	}	if (temp & ALI15X3_STS_TERM) {		result = -1;		dev_dbg(&adap->dev, "Error: Failed bus transaction\n");	}	/*	  Unfortunately the ALI SMB controller maps "no response" and "bus	  collision" into a single bit. No reponse is the usual case so don't	  do a printk.	  This means that bus collisions go unreported.	*/	if (temp & ALI15X3_STS_COLL) {		result = -1;		dev_dbg(&adap->dev,			"Error: no response or bus collision ADD=%02x\n",			inb_p(SMBHSTADD));	}	/* haven't ever seen this */	if (temp & ALI15X3_STS_DEV) {		result = -1;		dev_err(&adap->dev, "Error: device error\n");	}	dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),		inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),		inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));	return result;}/* Return -1 on error. */static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,		   unsigned short flags, char read_write, u8 command,		   int size, union i2c_smbus_data * data){	int i, len;	int temp;	int timeout;	/* clear all the bits (clear-on-write) */	outb_p(0xFF, SMBHSTSTS);	/* make sure SMBus is idle */	temp = inb_p(SMBHSTSTS);	for (timeout = 0;	     (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);	     timeout++) {		msleep(1);		temp = inb_p(SMBHSTSTS);	}	if (timeout >= MAX_TIMEOUT) {		dev_err(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp);	}	switch (size) {	case I2C_SMBUS_PROC_CALL:		dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");		return -1;	case I2C_SMBUS_QUICK:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		size = ALI15X3_QUICK;		break;	case I2C_SMBUS_BYTE:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		if (read_write == I2C_SMBUS_WRITE)			outb_p(command, SMBHSTCMD);		size = ALI15X3_BYTE;		break;	case I2C_SMBUS_BYTE_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		outb_p(command, SMBHSTCMD);		if (read_write == I2C_SMBUS_WRITE)			outb_p(data->byte, SMBHSTDAT0);		size = ALI15X3_BYTE_DATA;		break;	case I2C_SMBUS_WORD_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		outb_p(command, SMBHSTCMD);		if (read_write == I2C_SMBUS_WRITE) {			outb_p(data->word & 0xff, SMBHSTDAT0);			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);		}		size = ALI15X3_WORD_DATA;		break;	case I2C_SMBUS_BLOCK_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		outb_p(command, SMBHSTCMD);		if (read_write == I2C_SMBUS_WRITE) {			len = data->block[0];			if (len < 0) {				len = 0;				data->block[0] = len;			}			if (len > 32) {				len = 32;				data->block[0] = len;			}			outb_p(len, SMBHSTDAT0);			/* Reset SMBBLKDAT */			outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);			for (i = 1; i <= len; i++)				outb_p(data->block[i], SMBBLKDAT);		}		size = ALI15X3_BLOCK_DATA;		break;	}	outb_p(size, SMBHSTCNT);	/* output command */	if (ali15x3_transaction(adap))	/* Error in transaction */		return -1;	if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))		return 0;	switch (size) {	case ALI15X3_BYTE:	/* Result put in SMBHSTDAT0 */		data->byte = inb_p(SMBHSTDAT0);		break;	case ALI15X3_BYTE_DATA:		data->byte = inb_p(SMBHSTDAT0);		break;	case ALI15X3_WORD_DATA:		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);		break;	case ALI15X3_BLOCK_DATA:		len = inb_p(SMBHSTDAT0);		if (len > 32)			len = 32;		data->block[0] = len;		/* Reset SMBBLKDAT */		outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);		for (i = 1; i <= data->block[0]; i++) {			data->block[i] = inb_p(SMBBLKDAT);			dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n",				len, i, data->block[i]);		}		break;	}	return 0;}static u32 ali15x3_func(struct i2c_adapter *adapter){	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |	    I2C_FUNC_SMBUS_BLOCK_DATA;}static struct i2c_algorithm smbus_algorithm = {	.name		= "Non-I2C SMBus adapter",	.id		= I2C_ALGO_SMBUS,	.smbus_xfer	= ali15x3_access,	.functionality	= ali15x3_func,};static struct i2c_adapter ali15x3_adapter = {	.owner		= THIS_MODULE,	.class          = I2C_CLASS_HWMON,	.algo		= &smbus_algorithm,	.name		= "unset",};static struct pci_device_id ali15x3_ids[] = {	{	.vendor =	PCI_VENDOR_ID_AL,	.device =	PCI_DEVICE_ID_AL_M7101,	.subvendor =	PCI_ANY_ID,	.subdevice =	PCI_ANY_ID,	},	{ 0, }};static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id){	if (ali15x3_setup(dev)) {		dev_err(&dev->dev,			"ALI15X3 not detected, module not inserted.\n");		return -ENODEV;	}	/* set up the driverfs linkage to our parent device */	ali15x3_adapter.dev.parent = &dev->dev;	snprintf(ali15x3_adapter.name, I2C_NAME_SIZE,		"SMBus ALI15X3 adapter at %04x", ali15x3_smba);	return i2c_add_adapter(&ali15x3_adapter);}static void __devexit ali15x3_remove(struct pci_dev *dev){	i2c_del_adapter(&ali15x3_adapter);	release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);}static struct pci_driver ali15x3_driver = {	.name		= "ali15x3 smbus",	.id_table	= ali15x3_ids,	.probe		= ali15x3_probe,	.remove		= __devexit_p(ali15x3_remove),};static int __init i2c_ali15x3_init(void){	return pci_module_init(&ali15x3_driver);}static void __exit i2c_ali15x3_exit(void){	pci_unregister_driver(&ali15x3_driver);}MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "		"Philip Edelbrock <phil@netroedge.com>, "		"and Mark D. Studebaker <mdsxyz123@yahoo.com>");MODULE_DESCRIPTION("ALI15X3 SMBus driver");MODULE_LICENSE("GPL");module_init(i2c_ali15x3_init);module_exit(i2c_ali15x3_exit);

⌨️ 快捷键说明

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