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

📄 i2c-ali1535.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	outb_p(0xFF, SMBHSTPORT);	/* We will always wait for a fraction of a second! */	timeout = 0;	do {		msleep(1);		temp = inb_p(SMBHSTSTS);	} while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE))		 && (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 & ALI1535_STS_FAIL) {		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 & ALI1535_STS_BUSERR) {		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 & ALI1535_STS_DEV) {		result = -1;		dev_err(&adap->dev, "Error: device error\n");	}	/* check to see if the "command complete" indication is set */	if (!(temp & ALI1535_STS_DONE)) {		result = -1;		dev_err(&adap->dev, "Error: command never completed\n");	}	dev_dbg(&adap->dev, "Transaction (post): STS=%02x, TYP=%02x, "		"CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",		inb_p(SMBHSTSTS), inb_p(SMBHSTTYP), inb_p(SMBHSTCMD),		inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));	/* take consequent actions for error conditions */	if (!(temp & ALI1535_STS_DONE)) {		/* issue "kill" to reset host controller */		outb_p(ALI1535_KILL,SMBHSTTYP);		outb_p(0xFF,SMBHSTSTS);	} else if (temp & ALI1535_STS_ERR) {		/* issue "timeout" to reset all devices on bus */		outb_p(ALI1535_T_OUT,SMBHSTTYP);		outb_p(0xFF,SMBHSTSTS);	}	return result;}/* Return -1 on error. */static s32 ali1535_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;	s32 result = 0;	down(&i2c_ali1535_sem);	/* make sure SMBus is idle */	temp = inb_p(SMBHSTSTS);	for (timeout = 0;	     (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE);	     timeout++) {		msleep(1);		temp = inb_p(SMBHSTSTS);	}	if (timeout >= MAX_TIMEOUT)		dev_warn(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp);	/* clear status register (clear-on-write) */	outb_p(0xFF, SMBHSTSTS);	switch (size) {	case I2C_SMBUS_PROC_CALL:		dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");		result = -1;		goto EXIT;	case I2C_SMBUS_QUICK:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		size = ALI1535_QUICK;		outb_p(size, SMBHSTTYP);	/* output command */		break;	case I2C_SMBUS_BYTE:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		size = ALI1535_BYTE;		outb_p(size, SMBHSTTYP);	/* output command */		if (read_write == I2C_SMBUS_WRITE)			outb_p(command, SMBHSTCMD);		break;	case I2C_SMBUS_BYTE_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		size = ALI1535_BYTE_DATA;		outb_p(size, SMBHSTTYP);	/* output command */		outb_p(command, SMBHSTCMD);		if (read_write == I2C_SMBUS_WRITE)			outb_p(data->byte, SMBHSTDAT0);		break;	case I2C_SMBUS_WORD_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		size = ALI1535_WORD_DATA;		outb_p(size, SMBHSTTYP);	/* output command */		outb_p(command, SMBHSTCMD);		if (read_write == I2C_SMBUS_WRITE) {			outb_p(data->word & 0xff, SMBHSTDAT0);			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);		}		break;	case I2C_SMBUS_BLOCK_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		size = ALI1535_BLOCK_DATA;		outb_p(size, SMBHSTTYP);	/* output command */		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(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP);			for (i = 1; i <= len; i++)				outb_p(data->block[i], SMBBLKDAT);		}		break;	}	if (ali1535_transaction(adap)) {		/* Error in transaction */		result = -1;		goto EXIT;	}	if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) {		result = 0;		goto EXIT;	}	switch (size) {	case ALI1535_BYTE:	/* Result put in SMBHSTDAT0 */		data->byte = inb_p(SMBHSTDAT0);		break;	case ALI1535_BYTE_DATA:		data->byte = inb_p(SMBHSTDAT0);		break;	case ALI1535_WORD_DATA:		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);		break;	case ALI1535_BLOCK_DATA:		len = inb_p(SMBHSTDAT0);		if (len > 32)			len = 32;		data->block[0] = len;		/* Reset SMBBLKDAT */		outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP);		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;	}EXIT:	up(&i2c_ali1535_sem);	return result;}u32 ali1535_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	= ali1535_access,	.functionality	= ali1535_func,};static struct i2c_adapter ali1535_adapter = {	.owner		= THIS_MODULE,	.class          = I2C_CLASS_HWMON,	.algo		= &smbus_algorithm,	.name		= "unset",};static struct pci_device_id ali1535_ids[] = {	{		.vendor =	PCI_VENDOR_ID_AL,		.device =	PCI_DEVICE_ID_AL_M7101,		.subvendor =	PCI_ANY_ID,		.subdevice =	PCI_ANY_ID,	},	{ },};static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id){	if (ali1535_setup(dev)) {		dev_warn(&dev->dev,			"ALI1535 not detected, module not inserted.\n");		return -ENODEV;	}	/* set up the driverfs linkage to our parent device */	ali1535_adapter.dev.parent = &dev->dev;	snprintf(ali1535_adapter.name, I2C_NAME_SIZE, 		"SMBus ALI1535 adapter at %04x", ali1535_smba);	return i2c_add_adapter(&ali1535_adapter);}static void __devexit ali1535_remove(struct pci_dev *dev){	i2c_del_adapter(&ali1535_adapter);	release_region(ali1535_smba, ALI1535_SMB_IOSIZE);}static struct pci_driver ali1535_driver = {	.name		= "ali1535_smbus",	.id_table	= ali1535_ids,	.probe		= ali1535_probe,	.remove		= __devexit_p(ali1535_remove),};static int __init i2c_ali1535_init(void){	return pci_module_init(&ali1535_driver);}static void __exit i2c_ali1535_exit(void){	pci_unregister_driver(&ali1535_driver);}MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "	      "Philip Edelbrock <phil@netroedge.com>, "	      "Mark D. Studebaker <mdsxyz123@yahoo.com> "	      "and Dan Eaton <dan.eaton@rocketlogix.com>");MODULE_DESCRIPTION("ALI1535 SMBus driver");MODULE_LICENSE("GPL");module_init(i2c_ali1535_init);module_exit(i2c_ali1535_exit);

⌨️ 快捷键说明

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