📄 i2c.c
字号:
outl(0xffff, I2SCLH); /* 设置高电平时间 */
outl(0xffff, I2SCLL); /* 设置低电平时间 */
sema_init(&sem, 1);
sema_init(&irq_sem, 0);
filp->private_data = (void *)num;
local_irq_restore(flag);
} usage++;
MOD_INC_USE_COUNT; return 0; /* success */} /*********************************************************************************************************
** Function name: i2c_release
** Descriptions: release device
** Input:inode: information of device
** filp: pointer of file
** Output 0: OK
** other: not OK
** Created by: Chenmingji
** Created Date: 2005-5-17
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static int i2c_release(struct inode *inode, struct file *filp) { unsigned long flag; u32 temp;
MOD_DEC_USE_COUNT; usage--;
if (usage == 0)
{
local_irq_save(flag);
temp = inl(PINSEL0);
temp &= ~(0x0f << 4);
temp |= PinSel0Save;
outl(temp, PINSEL0);
local_irq_restore(flag);
free_irq(IRQ_I2C, NULL);
}
return(0); } /*********************************************************************************************************
** Function name: i2c_ioctl
** Descriptions: IO control function
** Input:inode: information of device
** filp: pointer of file
** cmd: command
** arg: additive parameter
** Output 0: OK
** other: not OK
** Created by: Chenmingji
** Created Date: 2005-5-17
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static int i2c_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){
if (_IOC_TYPE(cmd) != I2C_IOC_MAGIC) { return -ENOTTY; } if (_IOC_NR(cmd) >= I2C_MAXNR) { return -ENOTTY; }
switch(cmd) { case I2C_SET_CLH:
if (arg < 4)
{
arg = 4;
}
outl(arg, I2SCLH); /* 设置高电平时间 */
break; case I2C_SET_CLL:
if (arg < 4)
{
arg = 4;
}
outl(arg, I2SCLL); /* 设置低电平时间 */
break; default: return -ENOTTY; break; } return 0;}
/*********************************************************************************************************
** Function name: i2c_irq_handle
** Descriptions: The top-half interrupt handler
** Input:
** Output none
** Created by: Chenmingji
** Created Date: 2005-5-17
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static void i2c_irq_handle(int irq, void *dev_id, struct pt_regs *regs){
unsigned int temp;
temp = inl(I2STAT);
switch(temp & 0xf8)
{
case 0x08: /* 已发送起始条件,与0x10相同处理 */
case 0x10: /* 已发送重复起始条件 */
outl(I2cAddr, I2DAT); /* 发送地址 */
outl(0x28, I2CONCLR); /* 清除标志 */
break;
case 0x18: /* 已发送SLA+W,并已接收应答 */
get_user(temp, (u8 *)I2cBuf);
outl(temp, I2DAT);
I2cBuf++;
I2cNbyte--;
outl(0x28, I2CONCLR); /* 清除标志 */
break;
case 0x28: /* 已发送I2C数据,并接收到应答 */
if (I2cNbyte > 0)
{
get_user(temp, (u8 *)I2cBuf);
outl(temp, I2DAT);
outl(0x28, I2CONCLR); /* 清除标志 */
I2cBuf++;
I2cNbyte--;
}
else
{
outl(0x28, I2CONCLR); /* 清除标志 */
outl(1 << 4, I2CONSET); /* 结束总线 */
up(&irq_sem);
}
break;
case 0x20: /* 已发送SLA+W;已接收非ACK, 与0x48处理相同 */
case 0x30: /* 已发送I2DAT中的数据字节;已接收非ACK, 与0x48处理相同 */
case 0x48: /* 已发送SLA+R;已接收非ACK */
outl(1 << 4, I2CONSET); /* 发送停止信号 */
outl(0x28, I2CONCLR); /* 清除标志 */
up(&irq_sem);
break;
case 0x38: /* 在SLA+R/W或数据字节中丢失仲裁 */
outl(0x28, I2CONCLR); /* 清除标志 */
up(&irq_sem);
break;
case 0x40: /* 已发送SLA+R;已接收ACK */
if (I2cNbyte <= 1)
{
outl(1 << 2, I2CONCLR); /* 下次发送非应答信号 */
}
else
{
outl(1 << 2, I2CONSET); /* 下次发送应答信号 */
}
outl(0x28, I2CONCLR); /* 清除标志 */
break;
case 0x50: /* 已接收数据字节;已发送ACK */
temp = inl(I2DAT);
put_user(temp, (u8 *)I2cBuf);
/* 接收数据 */
I2cBuf++;
I2cNbyte--;
if (I2cNbyte <= 1)
{
outl(1 << 2, I2CONCLR); /* 下次发送非应答信号 */
}
outl(0x28, I2CONCLR); /* 清除标志 */
break;
case 0x58: /* 已接收数据字节;已返发送非ACK */
temp = inl(I2DAT);
put_user(temp, (u8 *)I2cBuf);
/* 接收数据 */
I2cNbyte--;
outl(1 << 4, I2CONSET); /* 结束总线 */
outl(0x28, I2CONCLR); /* 清除标志 */
up(&irq_sem);
break;
default:
outl(0x28, I2CONCLR); /* 清除标志 */
break;
}
}
/*********************************************************************************************************
** Function name: i2c_init
** Descriptions: init driver
** Input:none
** Output 0: OK
** other: not OK
** Created by: Chenmingji
** Created Date: 2005-5-17
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int i2c_init(void){ int result;
result = register_chrdev(MAJOR_NR, DEVICE_NAME, &i2c_fops); if (result < 0) { printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n", MAJOR_NR ); return(result); }
if (MAJOR_NR == 0) { MAJOR_NR = result; /* dynamic */ }
printk(KERN_INFO DEVICE_NAME ": init OK\n"); return(0); }/*********************************************************************************************************
** Function name: i2c_cleanup
** Descriptions: exit driver
** Input:none
** Output none
** Created by: Chenmingji
** Created Date: 2005-5-17
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void i2c_cleanup(void){
unregister_chrdev(MAJOR_NR, DEVICE_NAME);}/*********************************************************************************************************** End Of File********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -