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

📄 i2c-gm-adap.c

📁 基于GM8180,NSF2200F的I2C驱动,LINUX平台
💻 C
📖 第 1 页 / 共 2 页
字号:
    unsigned char *p;
    
    p=buf ;
    if(! (client = kmalloc(sizeof(struct GMi2c_i2c_client),GFP_KERNEL)))
	return ;
    memcpy(client,&i2cdev_client_template,sizeof(struct i2c_client));
    client->adapter = &bit_i2c_adapter; 
    
    client->adapter->flags = EEPROM_ID_WRITE; 	//I2C device address
    client->adapter->data = start_addr ;		//I2C offset
    for (i=0 ; i<size ; i++) {
    	ret = i2c_master_send(client,p,1);
    	if (ret != 1){
		printk("i2c-GM-adap.o: I2C Write error(ret:0x%x), reg = 0x%x, data = 0x%x!\n",ret,client->adapter->data,*p);
    	}
    	client->adapter->data++ ;	
	p++;
    }
	//status = bit_eeprom_adapter.algo->master_xfer(&bit_eeprom_adapter,&msg,msg.len);
    kfree(client);
}

static unsigned int get_ahb_clk(void)
{
    return AHB_CLK_IN;
}

void adjust_timer(void)
{
    unsigned int timer_clk;

    timer_clk=get_ahb_clk()/2;
    printk("Adjust Timer to %d\n",timer_clk);
    *(volatile unsigned int *)(TIMER_FTTMR010_VA_BASE+0x4)=(timer_clk/HZ)-1;
}


//#define ADDR_2								// support 16 bit internal address
static unsigned int ken_u32PMU_ReadHCLK(void)
{
    return AHB_CLK_IN;
}


static unsigned int ken_u32PMU_ReadPCLK(void)
{
#if defined(CONFIG_PLATFORM_GM8120)
	if (inw(PMU_FTPMU010_VA_BASE+0x28) & BIT2)
		return (ken_u32PMU_ReadHCLK() >> 1);
	else
		return (ken_u32PMU_ReadHCLK());
#else
	return (AHB_CLK_IN >> 1);
#endif
}

void fLib_I2C_SetClockdiv_i(unsigned int count)
{
	//printk("i2c-GM-adap.o:count in fLib_I2C_SetClockdiv_i:%d\n",count);
	if ( count < 0 ) 
		return ;
	outl(count, I2C_FTI2C010_VA_BASE + I2C_ClockDiv);
}

int GM_fLib_I2C_SetClockdiv(unsigned int i_SCLout)	//i_CSCLout means I2C bus clock value , *1024
{
	int  i; 

	i_SCLout = i_SCLout *1024 ; 
	//printk("I2C bus Clock:%d",i_SCLout);
	
	if ( i_SCLout == 0 ){
		i_SCLout = I2C_Default_FREQ;		// default. clock is 45KHz
	}
	
	/*if (i_SCLout > I2C_MAX_FREQ || i_SCLout==0) {
		i_SCLout = I2C_MAX_FREQ;		// max. clock is 400KHz
	}
	*/
	//printk("i2c-GM-adap.o:Set I2C Bus Clock:0x%x\n",i_SCLout);
	i = (((ken_u32PMU_ReadPCLK() + i_SCLout - 1) / i_SCLout) +
		 ((I2C_GSR_Value & (BIT12 | BIT11 | BIT10)) >> 10) -
		 1 + 1	)/2;
	if (i >= BIT10) {
		printk("Pclk is to fast to form i2c clock, fail \n");
		return -1;
	}
	fLib_I2C_SetClockdiv_i(i);
	return 0;
}

void I2C_freq_init(void) {
	int SCLout,i ;
	
	SCLout = ken_u32PMU_ReadPCLK() /10;	// PCLK must 10 times of SCLout
	if (SCLout > I2C_MAX_FREQ)
	SCLout = I2C_MAX_FREQ;		// max. clock is 400KHz

	i = (((ken_u32PMU_ReadPCLK() + SCLout - 1) / SCLout) +
		 ((I2C_GSR_Value & (BIT12 | BIT11 | BIT10)) >> 10) -
		 1 + 1	)/2;
	if (i >= BIT10) {
		printk("Pclk is to fast to form i2c clock, fail \n");
		return -1;
	}
	printk("current Clock div i:0x%x\n",i);
	//GM_fLib_I2C_SetClockdiv(0x60);
	fLib_I2C_SetClockdiv_i(i);
}

int i2c_dev_init(void)
{

	int res;
    	printk("I2C_GM_ADAP_Version(%s) driver enable!\n",I2C_GM_ADAP_Version);
	
	I2C_freq_init();	
	i2cdev_initialized = 0;
	res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);
	if (res)
		goto out;
	res = class_register(&i2c_dev_class);
	if (res)
		goto out_unreg_chrdev;
	if (i2c_iic_add_bus(&bit_i2c_adapter) <0) {
    		printk("i2c_iic_add_bus fail!\n");
		return -1;
    	}
    	printk("i2c_iic_add_bus in i2c-GM-adap.c successfully!\n");	
	res = i2c_add_driver(&i2cdev_driver);
	if (res)
		goto out_unreg_class;
	devfs_mk_dir("i2c");
	printk("i2c_add_driver successfully!\n");
	return 0;	
out_unreg_class:
	class_unregister(&i2c_dev_class);
out_unreg_chrdev:
	unregister_chrdev(I2C_MAJOR, "i2c");
out:
	printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
	return res;	
}EXPORT_SYMBOL(i2c_dev_init);

void i2c_dev_exit(void)
{
	i2c_del_driver(&i2cdev_driver);
	i2c_iic_del_bus(&bit_i2c_adapter);
	class_unregister(&i2c_dev_class);
	devfs_remove("i2c");
	unregister_chrdev(I2C_MAJOR,"i2c");
}EXPORT_SYMBOL(i2c_dev_exit);

//Add By Ken.Hsieh for testing
int GM8120_get_mac_eeprom(unsigned char *macp)
{
    int i,j;
    unsigned char *mac=macp, set[6]={0x10,0x20,0x30,0x40,0x50,0x60};
    //unsigned char *mac=macp, set[6]={0x11,0x22,0x33,0x44,0x55,0x66};
    //Add By Ken.Hsieh
    //if set is "0x11,0x12,0x13,0x14,0x15,0x16, eth0 could ping successfully, but fail in ftp function"
    j=i=(unsigned int)&cfg.mac-(unsigned int)&cfg;
	
    //I2C_freq_init(); 
    //GM_fLib_I2C_SetClockdiv(0x60); 
    //printk("Set ClockDiv !\n");   
    //seeprom_write(CONFIG_START_ADDR+i,6,set);
    //printk("seeprom_write MAC successfully!\n");
    seeprom_read(CONFIG_START_ADDR+j,6,mac);
    printk("   MAC address[%02x%02x%02x%02x%02x%02x]:",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
    if((mac[0]==0)&&(mac[1]==0)&&(mac[2]==0)&&(mac[3]==0)&&(mac[4]==0)&&(mac[5]==0))
	return 0;
    if((mac[0]==0xff)&&(mac[1]==0xff)&&(mac[2]==0xff)&&(mac[3]==0xff)&&(mac[4]==0xff)&&(mac[5]==0xff))
        return 0;
    return 1;
}EXPORT_SYMBOL(GM8120_get_mac_eeprom);

int GM8120_tv_init1(char *buf,int length)
{
    int i;
    for(i=0;i<length;i++)
    {
    	seeprom_write(*(buf+i*2),1,(buf+i*2+1));
    }
    return 0;
}

int GM8120_tv_init2(char *buf,int length,unsigned char *macp)
{
    int i;
    for(i=0;i<length;i++)
    {
    	seeprom_write(*(buf+i*2),1,(buf+i*2+1));
    }
    return 0;
}

static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
                            loff_t *offset)
{
	char *tmp;
	int ret;
#ifdef DEBUG
	struct inode *inode = file->f_dentry->d_inode;
#endif /* DEBUG */
	struct i2c_client *client = (struct i2c_client *)file->private_data;
				
	/* copy user space data to kernel space. */
	tmp = kmalloc(count,GFP_KERNEL);
	if (tmp==NULL)
		return -ENOMEM;
#ifdef DEBUG
	printk("i2c-GM-adap.o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),
	       count);
#endif
	//Add By Ken.Hsieh 
	ret = i2c_master_recv(client,tmp,count);
	if (ret >= 0)
		ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
	kfree(tmp);
	return ret;
}

static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t count,
                             loff_t *offset)
{
	int ret;
	char *tmp;
	struct i2c_client *client = (struct i2c_client *)file->private_data;

	/* copy user space data to kernel space. */
	tmp = kmalloc(count,GFP_KERNEL);
	if (tmp==NULL)
		return -ENOMEM;
	if (copy_from_user(tmp,buf,count)) {
		kfree(tmp);
		return -EFAULT;
	}
#ifdef DEBUG
	printk("i2c-GM-adap.o: writing %d bytes:%2x.\n",
	       count,*buf);
#endif
	ret = i2c_master_send(client,tmp,count);
	kfree(tmp);
	return ret;
}

static int i2cdev_ioctl(struct inode *inode, struct file *file,
		unsigned int cmd, unsigned *arg)
{
	struct GMi2c_i2c_client *client = (struct GMi2c_i2c_client *)file->private_data;
	struct i2c_GM_msg *i2c_data ;
	int count ;
	int ret;
	char *tmp,*tmp1;

#ifdef DEBUG
	printk("i2c-GM-adap-adap.o: i2c-%d ioctl, cmd: 0x%x, arg: %s.\n", 
	       MINOR(inode->i_rdev),cmd, arg);
#endif /* DEBUG */

	switch ( cmd ) {
	case I2C_SLAVE:
		//Set address
		client->adapter->data = arg;
#ifdef DEBUG
		printk("i2c-GM-adap-adap.o:Setting adapter address:%2x in i2cdev_ioctl of i2c-GM-adap-adap.o \n",client->adapter->data);
#endif
		return 0;
	case I2C_SLAVE_FORCE:
		client->adapter->flags = arg;	
		return 0;
	case I2C_TENBIT:
		printk("i2c-GM-adap.o:Funciton I2C_TENBIT not support!\n");
		return 0;
	case I2C_PEC:
		printk("i2c-GM-adap.o:Funciton I2C_PEC not support!\n");
		return 0;		
	case I2C_FUNCS:
		printk("\nClock div:%d\n",arg);
		//GM_fLib_I2C_SetClockdiv(arg);	
		return 0;
        case I2C_RDWR:
		i2c_data = arg;
		//client->adapter->flags = i2c_data->addr;	//device address
		client->adapter->data = i2c_data->waddr;	//offset	
		client->adapter->client_count = i2c_data->clockdiv ;
		client->adapter->adap.retries = i2c_data->multiread_once;
		count = i2c_data->len;
		
		if(i2c_data->addr & 0x01)
			client->flags = I2C_M_RD;
		else
			client->flags = 0;
			
		client->adapter->flags = i2c_data->addr >> 1;
#ifdef DEBUG		
		printk("addr = 0x%x,waddr = 0x%x,len = 0x%x,buf= 0x%x,clockdiv = 0x%x\n",i2c_data->addr,i2c_data->waddr,i2c_data->len,i2c_data->buf,i2c_data->clockdiv);
#endif		
		tmp = kmalloc(count,GFP_KERNEL);
		tmp1 = tmp ;
		if (tmp==NULL){
			printk("%s:Alloc memory fault!\n",__FUNCTION__);
			return -ENOMEM;
		}
		if (copy_from_user(tmp,i2c_data->buf,count)) {
			printk("%s:copy from user fault!\n",__FUNCTION__);	
			kfree(tmp);
			return -EFAULT;
		}
		if (( client->flags & I2C_M_RD ) !=1 ) {
			ret = i2c_master_send(client,tmp,count);
		}
		else { 
			ret = i2c_master_recv(client,tmp,count);
			copy_to_user(i2c_data->buf,tmp,count);
		}
		kfree(tmp);
		return ret;
	case I2C_SMBUS:
		printk("i2c-GM-adap.o:Funciton I2C_SMBUS not support!\n");
		return 0;
	default:
		printk("i2c-GM-adap.o:Funciton default not support!\n");
		return 0;
	}
	return 0;
}

static int i2cdev_open (struct inode *inode, struct file *file)
{
	unsigned int minor = iminor(inode);
	struct i2c_client *client;
	struct i2c_adapter *adap;
	struct i2c_dev *i2c_dev;
	
//Add By Ken.Hsieh
	*(volatile unsigned int *)(I2C_ADDR+0x14)=1;
	*(volatile unsigned int *)(I2C_ADDR+0x8)=0x3e;    //0x40
	//printk("Init I2C_ADDR..\n");
//	adjust_timer();
	//I2C_freq_init();
	
	i2c_dev = i2c_dev_get_by_minor(minor);
	if (!i2c_dev)
		return -ENODEV;

	adap = i2c_get_adapter(i2c_dev->adap->nr);
	if (!adap)
		return -ENODEV;

	client = kmalloc(sizeof(*client), GFP_KERNEL);
	if (!client) {
		i2c_put_adapter(adap);
		return -ENOMEM;
	}

	memcpy(client, &i2cdev_client_template, sizeof(*client));
	/* registered with adapter, passed as client to user */
	client->adapter = adap;
	client->addr = Display_ID; 
	file->private_data = client;

#ifdef DEBUG
	printk("i2c-GM-adap.o: opened i2c-%d\n",minor);
#endif
	return 0;
}

static int i2cdev_release (struct inode *inode, struct file *file) 
{
	struct i2c_client *client = file->private_data;

	i2c_put_adapter(client->adapter);
	kfree(client);
	file->private_data = NULL;
	
	return 0;
}
unsigned int i2c_ready=0;

int GM_i2c_xfer(struct i2c_msg *msgs, int num, int clockdiv)
{
    extern int GM_i2c_doxfer(struct i2c_msg *msgs, int num);
    int ret = 0;
    I2C_LOCK((&bit_i2c_adapter));
	#if 0
    ret = GM_fLib_I2C_SetClockdiv(clockdiv);
    if (ret !=0 ) {
		printk("%s:Error in SetClockdiv of GM_i2c_write\n", __FUNCTION__);
		*(unsigned int *)(I2C_FTI2C010_0_VA_BASE+0x08) = 0xf9;
		*(unsigned int *)(I2C_FTI2C010_0_VA_BASE+0x14) = 0x417;
//		return ret;
    }
	#endif
	*(unsigned int *)(I2C_FTI2C010_0_VA_BASE+0x08) = 0xf9;
	*(unsigned int *)(I2C_FTI2C010_0_VA_BASE+0x14) = 0x417;
	//*(unsigned int *)(I2C_FTI2C010_0_VA_BASE+0x14) = 0x401;

    ret = GM_i2c_doxfer(msgs, num);
    I2C_UNLOCK((&bit_i2c_adapter));
    return ret;
}
EXPORT_SYMBOL(GM_i2c_xfer);
/*
static int i2cdev_close (struct inode *inode, struct file *file){
	printk("i2c-GM-adap.o:i2cdev_close..\n");
	i2cdev_ioctl(inode,file,I2C_SLAVE_FORCE,Display_ID)	
	return 0;
}
*/
/*
static int __init tv_init(void){
    printk("I2C_GM_ADAP_Version(%s) driver enable!\n",I2C_GM_ADAP_Version);
    seeprom_init();
}
*/
//module_init(i2c_dev_init);
MODULE_AUTHOR("GM Corp.");
MODULE_LICENSE("GM License");
EXPORT_SYMBOL(GM_i2c_read);
EXPORT_SYMBOL(GM_i2c_write);
EXPORT_SYMBOL(GM_fLib_I2C_SetClockdiv);

⌨️ 快捷键说明

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