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

📄 i2c-bfin-twi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			unsigned short flags, char read_write,			u8 command, int size, union i2c_smbus_data *data){	struct bfin_twi_iface *iface = adap->algo_data;	int rc = 0;	if (!(bfin_read_TWI_CONTROL() & TWI_ENA))		return -ENXIO;	while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {		yield();	}	iface->writeNum = 0;	iface->readNum = 0;	/* Prepare datas & select mode */	switch (size) {	case I2C_SMBUS_QUICK:		iface->transPtr = NULL;		iface->cur_mode = TWI_I2C_MODE_STANDARD;		break;	case I2C_SMBUS_BYTE:		if (data == NULL)			iface->transPtr = NULL;		else {			if (read_write == I2C_SMBUS_READ)				iface->readNum = 1;			else				iface->writeNum = 1;			iface->transPtr = &data->byte;		}		iface->cur_mode = TWI_I2C_MODE_STANDARD;		break;	case I2C_SMBUS_BYTE_DATA:		if (read_write == I2C_SMBUS_READ) {			iface->readNum = 1;			iface->cur_mode = TWI_I2C_MODE_COMBINED;		} else {			iface->writeNum = 1;			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;		}		iface->transPtr = &data->byte;		break;	case I2C_SMBUS_WORD_DATA:		if (read_write == I2C_SMBUS_READ) {			iface->readNum = 2;			iface->cur_mode = TWI_I2C_MODE_COMBINED;		} else {			iface->writeNum = 2;			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;		}		iface->transPtr = (u8 *)&data->word;		break;	case I2C_SMBUS_PROC_CALL:		iface->writeNum = 2;		iface->readNum = 2;		iface->cur_mode = TWI_I2C_MODE_COMBINED;		iface->transPtr = (u8 *)&data->word;		break;	case I2C_SMBUS_BLOCK_DATA:		if (read_write == I2C_SMBUS_READ) {			iface->readNum = 0;			iface->cur_mode = TWI_I2C_MODE_COMBINED;		} else {			iface->writeNum = data->block[0] + 1;			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;		}		iface->transPtr = data->block;		break;	default:		return -1;	}	iface->result = 0;	iface->manual_stop = 0;	iface->read_write = read_write;	iface->command = command;	iface->timeout_count = 10;	/* FIFO Initiation. Data in FIFO should be discarded before	 * start a new operation.	 */	bfin_write_TWI_FIFO_CTL(0x3);	SSYNC();	bfin_write_TWI_FIFO_CTL(0);	/* clear int stat */	bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);	/* Set Transmit device address */	bfin_write_TWI_MASTER_ADDR(addr);	SSYNC();	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;	add_timer(&iface->timeout_timer);	switch (iface->cur_mode) {	case TWI_I2C_MODE_STANDARDSUB:		bfin_write_TWI_XMT_DATA8(iface->command);		bfin_write_TWI_INT_MASK(MCOMP | MERR |			((iface->read_write == I2C_SMBUS_READ) ?			RCVSERV : XMTSERV));		SSYNC();		if (iface->writeNum + 1 <= 255)			bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);		else {			bfin_write_TWI_MASTER_CTL(0xff << 6);			iface->manual_stop = 1;		}		/* Master enable */		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));		break;	case TWI_I2C_MODE_COMBINED:		bfin_write_TWI_XMT_DATA8(iface->command);		bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);		SSYNC();		if (iface->writeNum > 0)			bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);		else			bfin_write_TWI_MASTER_CTL(0x1 << 6);		/* Master enable */		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));		break;	default:		bfin_write_TWI_MASTER_CTL(0);		if (size != I2C_SMBUS_QUICK) {			/* Don't access xmit data register when this is a			 * read operation.			 */			if (iface->read_write != I2C_SMBUS_READ) {				if (iface->writeNum > 0) {					bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));					if (iface->writeNum <= 255)						bfin_write_TWI_MASTER_CTL(iface->writeNum << 6);					else {						bfin_write_TWI_MASTER_CTL(0xff << 6);						iface->manual_stop = 1;					}					iface->writeNum--;				} else {					bfin_write_TWI_XMT_DATA8(iface->command);					bfin_write_TWI_MASTER_CTL(1 << 6);				}			} else {				if (iface->readNum > 0 && iface->readNum <= 255)					bfin_write_TWI_MASTER_CTL(iface->readNum << 6);				else if (iface->readNum > 255) {					bfin_write_TWI_MASTER_CTL(0xff << 6);					iface->manual_stop = 1;				} else {					del_timer(&iface->timeout_timer);					break;				}			}		}		bfin_write_TWI_INT_MASK(MCOMP | MERR |			((iface->read_write == I2C_SMBUS_READ) ?			RCVSERV : XMTSERV));		SSYNC();		/* Master enable */		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |			((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));		break;	}	SSYNC();	wait_for_completion(&iface->complete);	rc = (iface->result >= 0) ? 0 : -1;	return rc;}/* * Return what the adapter supports */static u32 bfin_twi_functionality(struct i2c_adapter *adap){	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |	       I2C_FUNC_I2C;}static struct i2c_algorithm bfin_twi_algorithm = {	.master_xfer   = bfin_twi_master_xfer,	.smbus_xfer    = bfin_twi_smbus_xfer,	.functionality = bfin_twi_functionality,};static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state){/*	struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/	/* Disable TWI */	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA);	SSYNC();	return 0;}static int i2c_bfin_twi_resume(struct platform_device *dev){/*	struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/	/* Enable TWI */	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);	SSYNC();	return 0;}static int i2c_bfin_twi_probe(struct platform_device *dev){	struct bfin_twi_iface *iface = &twi_iface;	struct i2c_adapter *p_adap;	int rc;	spin_lock_init(&(iface->lock));	init_completion(&(iface->complete));	iface->irq = IRQ_TWI;	init_timer(&(iface->timeout_timer));	iface->timeout_timer.function = bfin_twi_timeout;	iface->timeout_timer.data = (unsigned long)iface;	p_adap = &iface->adap;	p_adap->id = I2C_HW_BLACKFIN;	strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));	p_adap->algo = &bfin_twi_algorithm;	p_adap->algo_data = iface;	p_adap->class = I2C_CLASS_ALL;	p_adap->dev.parent = &dev->dev;	rc = request_irq(iface->irq, bfin_twi_interrupt_entry,		IRQF_DISABLED, dev->name, iface);	if (rc) {		dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n",			iface->irq);		return -ENODEV;	}	/* Set TWI internal clock as 10MHz */	bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);	/* Set Twi interface clock as specified */	bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )			<< 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )			& 0xFF));	/* Enable TWI */	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);	SSYNC();	rc = i2c_add_adapter(p_adap);	if (rc < 0)		free_irq(iface->irq, iface);	else		platform_set_drvdata(dev, iface);	return rc;}static int i2c_bfin_twi_remove(struct platform_device *pdev){	struct bfin_twi_iface *iface = platform_get_drvdata(pdev);	platform_set_drvdata(pdev, NULL);	i2c_del_adapter(&(iface->adap));	free_irq(iface->irq, iface);	return 0;}static struct platform_driver i2c_bfin_twi_driver = {	.probe		= i2c_bfin_twi_probe,	.remove		= i2c_bfin_twi_remove,	.suspend	= i2c_bfin_twi_suspend,	.resume		= i2c_bfin_twi_resume,	.driver		= {		.name	= "i2c-bfin-twi",		.owner	= THIS_MODULE,	},};static int __init i2c_bfin_twi_init(void){	pr_info("I2C: Blackfin I2C TWI driver\n");	return platform_driver_register(&i2c_bfin_twi_driver);}static void __exit i2c_bfin_twi_exit(void){	platform_driver_unregister(&i2c_bfin_twi_driver);}MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");MODULE_LICENSE("GPL");module_init(i2c_bfin_twi_init);module_exit(i2c_bfin_twi_exit);

⌨️ 快捷键说明

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