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

📄 i2c-core.c

📁 基于GM8180,NSF2200F的I2C驱动,LINUX平台
💻 C
📖 第 1 页 / 共 3 页
字号:
		"%d-%04x", i2c_adapter_id(adapter), client->addr);	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",		client->name, client->dev.bus_id);	device_register(&client->dev);	device_create_file(&client->dev, &dev_attr_client_name);		return 0;}int i2c_detach_client(struct i2c_client *client){	struct i2c_adapter *adapter = client->adapter;	int res = 0;		if ((client->flags & I2C_CLIENT_ALLOW_USE)	 && (client->usage_count > 0)) {		dev_warn(&client->dev, "Client [%s] still busy, "			 "can't detach\n", client->name);		return -EBUSY;	}	if (adapter->client_unregister)  {		res = adapter->client_unregister(client);		if (res) {			dev_err(&client->dev,				"client_unregister [%s] failed, "				"client not detached\n", client->name);			goto out;		}	}	down(&adapter->clist_lock);	list_del(&client->list);	init_completion(&client->released);	device_remove_file(&client->dev, &dev_attr_client_name);	device_unregister(&client->dev);	up(&adapter->clist_lock);	wait_for_completion(&client->released); out:	return res;}static int i2c_inc_use_client(struct i2c_client *client){	if (!try_module_get(client->driver->owner))		return -ENODEV;	if (!try_module_get(client->adapter->owner)) {		module_put(client->driver->owner);		return -ENODEV;	}	return 0;}static void i2c_dec_use_client(struct i2c_client *client){	module_put(client->driver->owner);	module_put(client->adapter->owner);}int i2c_use_client(struct i2c_client *client){	int ret;	ret = i2c_inc_use_client(client);	if (ret)		return ret;	if (client->flags & I2C_CLIENT_ALLOW_USE) {		if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)			client->usage_count++;		else if (client->usage_count > 0) 			goto busy;		else 			client->usage_count++;	}	return 0; busy:	i2c_dec_use_client(client);	return -EBUSY;}int i2c_release_client(struct i2c_client *client){	if(client->flags & I2C_CLIENT_ALLOW_USE) {		if(client->usage_count>0)			client->usage_count--;		else {			pr_debug("i2c-core: %s used one too many times\n",				__FUNCTION__);			return -EPERM;		}	}		i2c_dec_use_client(client);		return 0;}void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg){	struct list_head  *item;	struct i2c_client *client;	down(&adap->clist_lock);	list_for_each(item,&adap->clients) {		client = list_entry(item, struct i2c_client, list);		if (!try_module_get(client->driver->owner))			continue;		if (NULL != client->driver->command) {			up(&adap->clist_lock);			client->driver->command(client,cmd,arg);			down(&adap->clist_lock);		}		module_put(client->driver->owner);       }       up(&adap->clist_lock);}#define I2C_IRQ		19unsigned int status=0;irqreturn_t i2c_isr(void){    status = *(volatile unsigned int *)(I2C_ADDR+4);    //printk("[4]%x\n", status);	if(status & 0x30)	{		i2c_handler();	}	return IRQ_HANDLED;}static int __init i2c_init(void){	int retval;	int ret;	retval = bus_register(&i2c_bus_type);	if (retval)		return retval;		retval = driver_register(&i2c_adapter_driver);	if (retval)		return retval;		retval = class_register(&i2c_adapter_class);	if (retval)		return retval;			retval = i2c_dev_init();	if (retval)		return retval;	i2c_algo_iic_init();	//ret = request_irq(I2C_IRQ, i2c_isr, SA_INTERRUPT, 0, 0);	//if(ret < 0) 	//{	//	printk(KERN_ERR "request irq(%d) fail\n", I2C_IRQ);	//}	printk("I2C Hwarang\n");	return  0;		}static void __exit i2c_exit(void){	i2c_dev_exit();	class_unregister(&i2c_adapter_class);		driver_unregister(&i2c_adapter_driver);	bus_unregister(&i2c_bus_type);}//subsys_initcall(i2c_init);module_init(i2c_init);module_exit(i2c_exit);/* ---------------------------------------------------- * the functional interface to the i2c busses. * ---------------------------------------------------- */int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num){	int ret;	if (adap->algo->master_xfer) {#ifdef DEBUG		for (ret = 0; ret < num; ret++) {			dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "				"len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?				'R' : 'W', msgs[ret].addr, msgs[ret].len);		}#endif		down(&adap->bus_lock);		ret = adap->algo->master_xfer(adap,msgs,num);		up(&adap->bus_lock);		return ret;	} else {		dev_dbg(&adap->dev, "I2C level transfers not supported\n");		return -ENOSYS;	}}int i2c_master_send(struct i2c_client *client,const char *buf ,int count){	int ret;	struct i2c_adapter *adap=client->adapter;	struct i2c_msg msg;	msg.addr = client->addr;	//msg.flags = client->flags & I2C_M_TEN;	msg.len = count;	msg.buf = (char *)buf;		ret = i2c_transfer(adap, &msg, count);	/* If everything went ok (i.e. 1 msg transmitted), return #bytes	   transmitted, else error code. */	return (ret == 1) ? count : ret;}int i2c_master_recv(struct i2c_client *client, char *buf ,int count){	struct i2c_adapter *adap=client->adapter;	struct GMi2c_info *fara_info=client->adapter;	struct i2c_msg msg;	int ret,i;	msg.addr = client->addr;	msg.flags = client->flags & I2C_M_TEN;	msg.flags |= I2C_M_RD;	msg.len = count;	msg.buf = buf;#ifdef CONFIG_PLATFORM_GM8120	for (i=0 ; i < count ; i++) {//this type for cmos-driver, count > 1 for Tuner-AP 		msg.buf = buf;		ret = i2c_transfer(adap, &msg, 1);		if ( ret != 1 )			break;		*buf = *(msg.buf);		if ( count == 1 )				break;		//adap->data++;		fara_info->data++;		buf++;	}	//ret = i2c_transfer(adap, &msg, 1);#else		ret = i2c_transfer(adap, &msg, 1);#endif	/* If everything went ok (i.e. 1 msg transmitted), return #bytes	   transmitted, else error code. */	return (ret == 1) ? count : ret;}int i2c_control(struct i2c_client *client,	unsigned int cmd, unsigned long arg){	int ret = 0;	struct i2c_adapter *adap = client->adapter;	dev_dbg(&client->adapter->dev, "i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg);	switch (cmd) {		case I2C_RETRIES:			adap->retries = arg;			break;		case I2C_TIMEOUT:			adap->timeout = arg;			break;		default:			if (adap->algo->algo_control!=NULL)				ret = adap->algo->algo_control(adap,cmd,arg);	}	return ret;}/* ---------------------------------------------------- * the i2c address scanning function * Will not work for 10-bit addresses! * ---------------------------------------------------- */static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,			     int (*found_proc) (struct i2c_adapter *, int, int)){	int err;	/* Make sure the address is valid */	if (addr < 0x03 || addr > 0x77) {		dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",			 addr);		return -EINVAL;	}	/* Skip if already in use */	if (i2c_check_addr(adapter, addr))		return 0;	/* Make sure there is something at this address, unless forced */	if (kind < 0) {		if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,				   I2C_SMBUS_QUICK, NULL) < 0)			return 0;		/* prevent 24RF08 corruption */		if ((addr & ~0x0f) == 0x50)			i2c_smbus_xfer(adapter, addr, 0, 0, 0,				       I2C_SMBUS_QUICK, NULL);	}	/* Finally call the custom detection function */	err = found_proc(adapter, addr, kind);	/* -ENODEV can be returned if there is a chip at the given address	   but it isn't supported by this chip driver. We catch it here as	   this isn't an error. */	return (err == -ENODEV) ? 0 : err;}int i2c_probe(struct i2c_adapter *adapter,	      struct i2c_client_address_data *address_data,	      int (*found_proc) (struct i2c_adapter *, int, int)){	int i, err;	int adap_id = i2c_adapter_id(adapter);	/* Forget it if we can't probe using SMBUS_QUICK */	if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))		return -1;	/* Force entries are done first, and are not affected by ignore	   entries */	if (address_data->forces) {		unsigned short **forces = address_data->forces;		int kind;		for (kind = 0; forces[kind]; kind++) {			for (i = 0; forces[kind][i] != I2C_CLIENT_END;			     i += 2) {				if (forces[kind][i] == adap_id				 || forces[kind][i] == ANY_I2C_BUS) {					dev_dbg(&adapter->dev, "found force "						"parameter for adapter %d, "						"addr 0x%02x, kind %d\n",						adap_id, forces[kind][i + 1],						kind);					err = i2c_probe_address(adapter,						forces[kind][i + 1],						kind, found_proc);					if (err)						return err;				}			}		}	}	/* Probe entries are done second, and are not affected by ignore	   entries either */	for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {		if (address_data->probe[i] == adap_id		 || address_data->probe[i] == ANY_I2C_BUS) {			dev_dbg(&adapter->dev, "found probe parameter for "				"adapter %d, addr 0x%02x\n", adap_id,				address_data->probe[i + 1]);			err = i2c_probe_address(adapter,						address_data->probe[i + 1],						-1, found_proc);			if (err)				return err;		}	}	/* Normal entries are done last, unless shadowed by an ignore entry */	for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {		int j, ignore;		ignore = 0;		for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;		     j += 2) {			if ((address_data->ignore[j] == adap_id ||			     address_data->ignore[j] == ANY_I2C_BUS)			 && address_data->ignore[j + 1]			    == address_data->normal_i2c[i]) {				dev_dbg(&adapter->dev, "found ignore "					"parameter for adapter %d, "					"addr 0x%02x\n", adap_id,					address_data->ignore[j + 1]);			}			ignore = 1;			break;		}		if (ignore)			continue;		dev_dbg(&adapter->dev, "found normal entry for adapter %d, "			"addr 0x%02x\n", adap_id,			address_data->normal_i2c[i]);		err = i2c_probe_address(adapter, address_data->normal_i2c[i],					-1, found_proc);		if (err)			return err;	}	return 0;}struct i2c_adapter* i2c_get_adapter(int id){	struct i2c_adapter *adapter;		down(&core_lists);	adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);	if (adapter && !try_module_get(adapter->owner))		adapter = NULL;	up(&core_lists);	return adapter;}void i2c_put_adapter(struct i2c_adapter *adap){	module_put(adap->owner);}/* The SMBus parts */#define POLY    (0x1070U << 3) static u8

⌨️ 快捷键说明

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