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

📄 i2c-imx.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
}/*----------------------------------------------------------------------------- * void i2c_imx_isr (s16 irq, void * dev_id, struct pt_regs * reg) * This function deals with the interrupt for the I2C module. * * Parameters:	irq		the interrupt number *              dev_id		device id * 	        reg		processor register	 * Return: 	IRQ_HANDLED	the own irq was handled *----------------------------------------------------------------------------*/static irqreturn_t i2c_imx_isr (s16 irq, void *dev_id, struct pt_regs * reg){	/* safe status register */	i2c_imx_i2sr = i2c_imx_reg->i2sr;	/* if data transfer is complete set ok */	if (i2c_imx_i2sr & (u32)0x80)  /* [I2SR:ICF] TX complete */		i2c_imx_irq_ok = 1;	/* clear irq */	i2c_imx_reg->i2sr &= ~(u32)0x02; /* clear [I2SR:IIF] Interrupt */	return IRQ_HANDLED;}/*----------------------------------------------------------------------------- * int i2c_imx_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[ ], * SINT16 num) * This function is responsible for the transfer of the data through the * I2C bus *  * Parameter:   i2c_adap	associated with the related hardware *              msgs[ ] 	the body of the message to be send out *              num		number of message * Return:      Success		Number of message has been transferred *	        Failure		-err (error code) *----------------------------------------------------------------------------*/static int i2c_imx_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],			int num){	int i, count=0, err=0;	unsigned long jif = i2c_imx_slp[msgs[0].addr-1].jif;	int slp_time = i2c_imx_slp[msgs[0].addr-1].slp_time;	int slp = slp_time * HZ / 1000 - (jiffies - jif);	DECLARE_WAIT_QUEUE_HEAD(wait);	/* scheduler: sleep while chip not ready */	if ((slp > 1) && (msgs[0].flags & I2C_M_RD)) {		up(&i2c_adap->bus_lock);		sleep_on_timeout(&wait, slp);		down(&i2c_adap->bus_lock);	}	/* enable the i2c-bus, disable the I2C transmit ACK */	if(i2c_imx_bus_busy()) goto ERROR;	i2c_imx_reg->i2cr |= (u32)0x80;	i2c_imx_reg->i2cr |= (u32)0x08;	for ( i = 0; i < num; i ++) {		/* repeat start else start the bus-transfer */		if(i) {			i2c_imx_reg->i2cr |= (u32)0x04;		} else {			if ((err = i2c_imx_start())) goto ERROR;		}		/* enable interrupt, enable master transmit */		i2c_imx_reg->i2cr |= (u32)0x40;		i2c_imx_reg->i2cr |= (u32)0x10;		/* write/read data */		if (!(msgs[i].flags & I2C_M_RD )) {			if ((err = i2c_imx_write(i, &count, &msgs[i]))) goto ERROR;		} else {			if ((err = i2c_imx_read(i, &count, &msgs[i]))) goto ERROR;		}	}	/*exit function and error handler */	i2c_imx_reg->i2cr &= ~((u32)0x20); /* bus stop */	i2c_imx_bus_release();	i2c_imx_reg->i2cr &= ~((u32)0x80); /* disable I2C */	if (!(msgs[0].flags & I2C_M_RD )) chip_slp(&msgs[0]);	  		i2c_imx_slp[msgs[0].addr-1].jif = jiffies;	return count; ERROR:#ifdef DEBUG	printk("ERROR%d\n", err);	if(err == 1) i2c_imx_errs_rxack++;	if(err == 2) i2c_imx_errs_txcomplete++;	if(err == 3) i2c_imx_errs_busbusy++;	if(err == 4) i2c_imx_errs_busgrab++;#endif	/* reset the i2c-bus (hopefully not needed */	i2c_imx_reg->i2cr = (u32)0x00;	GIUS(0) |=  0x00018000;	udelay(100);  	imx_gpio_mode(PA15_PF_I2C_SDA);	mdelay(1);	i2c_imx_slp[msgs[0].addr-1].jif = jiffies;	return -err;}/*----------------------------------------------------------------------------- * int i2c_smbus_imx_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[ ], * SINT16 num) * This function is responsible for the transfer of the data through the * I2C-bus *  * Parameter : i2c_adap	the structure associated with the related hardware *             msgs[ ]	the body of the message to be send out *             num	number of message * Return :    Success  Number of message has been transferred *	       Failure  -1	 *----------------------------------------------------------------------------*/static int i2c_imx_smbus(struct i2c_adapter * adapter, u16 addr,			 unsigned short flags, char read_write, u8 command,			 int size,  union i2c_smbus_data * data){	char msgbuf0[34];	char msgbuf1[34];	int num = read_write == I2C_SMBUS_READ?2:1;	struct i2c_msg msg[2] = {		{ addr, flags, 1, msgbuf0 }, 		{ addr, flags | I2C_M_RD, 10, msgbuf1 }	};	int i;	msgbuf0[0] = command;	/* select the smbus-command and create the message */	switch(size) {	case I2C_SMBUS_QUICK:		msg[0].len = 0;		msg[0].flags=flags|(read_write==I2C_SMBUS_READ)?I2C_M_RD:0;		num = 1;		break;	case I2C_SMBUS_BYTE:		if (read_write == I2C_SMBUS_READ) {			msg[0].flags = I2C_M_RD | flags;			num = 1;		}		break;	case I2C_SMBUS_BYTE_DATA:		if (read_write == I2C_SMBUS_READ)			msg[1].len = 1;		else {			msg[0].len = 2;			msgbuf0[1] = data->byte;		}		break;	case I2C_SMBUS_WORD_DATA:		if (read_write == I2C_SMBUS_READ)			msg[1].len = 2;		else {			msg[0].len=3;			msgbuf0[1] = data->word & 0xff;			msgbuf0[2] = (data->word >> 8) & 0xff;		}		break;	case I2C_SMBUS_PROC_CALL:		num = 2;		msg[0].len = 3;		msg[1].len = 2;		msgbuf0[1] = data->word & 0xff;		msgbuf0[2] = (data->word >> 8) & 0xff;		break;	case I2C_SMBUS_BLOCK_DATA:		if (read_write == I2C_SMBUS_READ) {			return -1;		} else {			msg[0].len = data->block[0] + 2;			if (msg[0].len > 34) {				return -1;			}			for (i = 1; i <= msg[0].len; i++)				msgbuf0[i] = data->block[i-1];		}		break;	default:		return -1;	}	/* call the bus access routine */	if (i2c_imx_xfer(adapter, msg, num) < 0) return -1;	/* copy the readed bytes to the data-field */	if (read_write == I2C_SMBUS_READ)		switch(size) {		case I2C_SMBUS_BYTE:			data->byte = msgbuf0[0];			break;		case I2C_SMBUS_BYTE_DATA:			data->byte = msgbuf1[0];			break;		case I2C_SMBUS_WORD_DATA: 		case I2C_SMBUS_PROC_CALL:			data->word = msgbuf1[0] | (msgbuf1[1] << 8);			break;		}	return 0;}/*----------------------------------------------------------------------------- * int i2c_imx_ioctl(struct i2c_adapter * adapter, unsigned int cmd, * unsigned long arg) * This function control the I2C module itself * * Parameters:	Adapter		the adapter associated to the I2C module * 	        Cmd		IO control command * 	        Arg		argument associated with the command * Return : 	Success		0 *----------------------------------------------------------------------------*/static int i2c_imx_ioctl(struct i2c_adapter * adapter, unsigned int cmd,			 unsigned long arg){	switch( cmd ) {	case I2C_IO_CHANGE_FREQ:		i2c_imx_reg->ifdr = (u32)(arg & 0x003f);		break;	case I2C_IO_GET_STATUS:		arg = i2c_imx_reg->i2sr; 		break;	}	return 0;}/*----------------------------------------------------------------------------- * int __init i2c_imx_init(void) * initializes the I2C module in the DBIMX, and registers itself to the  * Linux I2C system * * Parameters: None * Return:      0: indicates SUCCESS *             -1: indicates FAILURE *----------------------------------------------------------------------------*/static int __init i2c_imx_init(void){	/* Pin Configuration for I2C:	 * 2 Pins are available for the I2C-Module. These Pins are multiplexed	 * with other functions on the device and must be configured for SPI-	 * Operation.	 * The Data Direction Bits in the GPIO Data Direction Register Port A	 * must be set for Output.	 * The Function Bits in the GPIO In Use Register Port A must be set	 * for Multiplexed.	 * Data Direction (DDIR): Output	 * GPIO-Function (GIUS):  SPI-Operation	 * GPR, PUEN:             for Interrupt operations */  	imx_gpio_mode(PA15_PF_I2C_SDA);  	imx_gpio_mode(PA16_PF_I2C_SCL);	/* install the I2C_IMX ISR to the Linux Kernel */	if(request_irq(I2C_INT, (void *)i2c_imx_isr, SA_INTERRUPT,		       "I2C_IMX", "i2c_bus")<0) return -1;  	/* Set clock Freq. */	i2c_imx_reg->ifdr = (u32)DEFAULT_FREQ;  	/* add the I2C adapter/algorithm driver to the linux kernel */	if (i2c_add_adapter(&i2c_imx_adapter)) return -1;#ifdef DEBUG	printk("I2C-Adapter %d installed. use device with Minor %d\n",	       i2c_imx_adapter.nr, i2c_imx_adapter.nr);#endif	/* define ms to sleep after read from chip*/	i2c_imx_slp[0x48-1].jif = jiffies;	i2c_imx_slp[0x48-1].slp_time = 1;	i2c_imx_slp[0x68-1].jif = jiffies;	i2c_imx_slp[0x68-1].slp_time = 200;	return 0;}/*----------------------------------------------------------------------------- * void __exit i2c_imx_cleanup(void) * This routine is called when the driver is unloaded * * Parameters: None * Return:     None *----------------------------------------------------------------------------*/static void __exit i2c_imx_cleanup(void){#ifdef DEBUG	printk("RX ACK      ERRORs: %d\n", i2c_imx_errs_rxack);	printk("TX COMPLETE ERRORs: %d\n", i2c_imx_errs_txcomplete);	printk("BUS BUSY    ERRORs: %d\n", i2c_imx_errs_busbusy);	printk("BUS GRAB    ERRORs: %d\n", i2c_imx_errs_busgrab);#endif	/* unset IEN[I2CR:7] (I2C Disable) */	i2c_imx_reg->i2cr = (u32)0x00;  	/* Free IRQ */	free_irq (I2C_INT, "i2c_bus");  	/* Delete Adapter from Kernel */  	i2c_del_adapter(&i2c_imx_adapter);	}/****************************************************************************** * Module Init/Exit ******************************************************************************/MODULE_AUTHOR("GSG China");MODULE_DESCRIPTION("I2C Adapter/Algorithm driver");MODULE_LICENSE("GPL");module_init(i2c_imx_init);module_exit(i2c_imx_cleanup);

⌨️ 快捷键说明

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