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

📄 ds2786_battery.c

📁 锂电池电量检测芯片ds2786驱动程序(参照linux/driver/power/ds2760_battery.c).在linux-2.6.24内核测试通过.
💻 C
📖 第 1 页 / 共 2 页
字号:
		di->full_counter = 0;	}	else if (di->current_uA < 10*1000 && di->charge_status != POWER_SUPPLY_STATUS_FULL)	{		/* Don't consider the battery to be full unless		* we've seen the current < 10 mA at least two		* consecutive times. **/		//POWER_SUPPLY_STATUS_NOT_CHARGING		di->full_counter++;				if (di->full_counter < 2)			di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;//POWER_SUPPLY_STATUS_CHARGING;		else			di->charge_status = POWER_SUPPLY_STATUS_FULL;	}	if (di->charge_status != old_charge_status)		power_supply_changed(&di->bat);}static void ds2786_battery_work(struct work_struct *work){	//struct ds2786_device_info *di = container_of(work,	//struct ds2786_device_info, monitor_work.work);	const int interval = HZ * 60;	//DBG("\n");	//dev_dbg(di->dev, "%s\n", __FUNCTION__);		ds2786_battery_update_status(di);	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);}#define to_ds2786_device_info(x) container_of((x), struct ds2786_device_info, \					      bat);static void ds2786_battery_external_power_changed(struct power_supply *psy){	//struct ds2786_device_info *di = to_ds2786_device_info(psy);	DBG("\n");	//dev_dbg(di->dev, "%s\n", __FUNCTION__);		cancel_delayed_work(&di->monitor_work);	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);}static int ds2786_battery_get_property(struct power_supply *psy,				       enum power_supply_property psp,				       union power_supply_propval *val){	//struct ds2786_device_info *di = to_ds2786_device_info(psy);	DBG("\n");	ds2786_battery_update_status(di);	switch (psp)	{		case POWER_SUPPLY_PROP_STATUS:			val->intval = di->charge_status;			return 0;		default:			break;	}	switch (psp)	{		case POWER_SUPPLY_PROP_VOLTAGE_NOW:			val->intval = di->voltage_uV;			break;		case POWER_SUPPLY_PROP_CURRENT_NOW:			val->intval = di->current_uA;			break;		case POWER_SUPPLY_PROP_CAPACITY:			val->intval = di->rem_capacity;			break;		case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:			val->intval = di->rated_capacity;			break;		case POWER_SUPPLY_PROP_CHARGE_FULL:			val->intval = di->full_active_uAh;			break;		case POWER_SUPPLY_PROP_CHARGE_EMPTY:			val->intval = di->empty_uAh;			break;		case POWER_SUPPLY_PROP_CHARGE_NOW:			val->intval = di->accum_current_uAh;			break;		case  POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:			val->intval = di->life_sec;			break;		case  POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:			val->intval = di->life_sec;			break;		case POWER_SUPPLY_PROP_TEMP:			val->intval = di->temp_C;			break;		case POWER_SUPPLY_PROP_ONLINE:			printk(KERN_ALERT"POWER_SUPPLY_PROP_ONLINE\n");			break;		default:			return -EINVAL;	}	dprintk(KERN_ALERT"val->intval=%d\n",val->intval);	return 0;}static enum power_supply_property ds2786_battery_props[] = {	POWER_SUPPLY_PROP_STATUS,	POWER_SUPPLY_PROP_VOLTAGE_NOW,	POWER_SUPPLY_PROP_CURRENT_NOW,	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,	POWER_SUPPLY_PROP_CHARGE_FULL,	POWER_SUPPLY_PROP_CHARGE_EMPTY,	POWER_SUPPLY_PROP_CHARGE_NOW,	POWER_SUPPLY_PROP_TEMP,};static int ds2786_init(void){	char buf[8];	DBG("\n");	i2c_ds2786_read(di->client,buf,DS2786_STATUS_CONFIG,1);	i2c_ds2786_read(di->client,buf+1,DS2786_RELATIVE_CAP,1);	if (buf[1]==0)	{		dprintk(KERN_ALERT"what's worry?\n");		buf[0] = DS2786_COMMAND;		buf[1] = 0x80;		i2c_ds2786_write(di->client, buf,1);		goto init_cap;	}	if (buf[0]&DS2786_PROF)	{init_cap:		dprintk(KERN_ALERT"ds2786 init\n");		buf[0] = DS2786_INITIAL_CAP;		buf[1] = 0x1d;//4400mAh		buf[2] = 0x08;//20mA		buf[3] = 0x04;//4.88mV/15min		buf[4] = 0x60;//I2c addr		buf[5] = 0x78;//60%		i2c_ds2786_write(di->client, buf,5);		i2c_ds2786_read(di->client,buf,DS2786_INITIAL_CAP,1);		printk(KERN_ALERT"ds2786_initial_cap=%d\n",(int)buf[0]);		buf[0] = DS2786_CURRENT_OFFSET_BIAS;		buf[1] = 0x02;//5mA		i2c_ds2786_write(di->client, buf,1);				buf[0]=DS2786_STATUS_CONFIG;		i2c_ds2786_read(di->client,buf+1,DS2786_STATUS_CONFIG,1);		buf[1]&=~((DS2786_SMOD) | (DS2786_PROF)) | DS2786_VODIS;		i2c_ds2786_write(di->client, buf,1);		i2c_ds2786_read(di->client,buf,DS2786_STATUS_CONFIG,1);		printk(KERN_ALERT"ds2786_status_config=%d\n",(int)buf[0]);				buf[0]=DS2786_COMMAND;		i2c_ds2786_read(di->client,buf+1,DS2786_COMMAND,1);		buf[1]|=DS2786_SOCV;		i2c_ds2786_write(di->client, buf,1);		udelay(20);		i2c_ds2786_read(di->client,buf,DS2786_COMMAND,1);		dprintk(KERN_ALERT"ds2786_command=%d\n",(int)buf[0]);		}		buf[0]=DS2786_INITIAL_CAP;	if (i2c_ds2786_read(di->client,buf,DS2786_INITIAL_CAP,1)==1);		di->rated_capacity = 128*1000000L/(long)buf[0];	printk(KERN_INFO"Initializing ds2786\n");}static irqreturn_t pwr_chang_irq(int irqno, void *dev_id){	ds2786_battery_external_power_changed(NULL);	printk(KERN_ALERT"PWR\n");	return IRQ_HANDLED;}static int ds2786_battery_probe(struct platform_device *pdev){	int retval = 0;	DBG("\n");	di = kzalloc(sizeof(*di), GFP_KERNEL);	if (!di)	{		retval = -ENOMEM;		goto di_alloc_failed;	}	platform_set_drvdata(pdev, di);	di->client==NULL;	di->ds2786_driver.id=I2C_DRIVERID_I2CDEV;	di->ds2786_driver.attach_adapter=ds2786_attach_adapter;	di->ds2786_driver.detach_client=ds2786_detach_client;	di->ds2786_driver.driver.name="ds2786";	retval=i2c_add_driver(&di->ds2786_driver);	if (retval | di->client==NULL)		goto batt_failed;	printk(KERN_ALERT"%retval: addr:%d\n",retval,di->client->addr);	if (di->client->addr!=0x36)		return -1;	ds2786_init();	//return 0;	di->dev		= &pdev->dev;	di->bat.name	   = pdev->dev.bus_id;	di->bat.type	   = POWER_SUPPLY_TYPE_BATTERY;	di->bat.properties     = ds2786_battery_props;	di->bat.num_properties = ARRAY_SIZE(ds2786_battery_props);	di->bat.get_property   = ds2786_battery_get_property;	di->bat.external_power_changed =				  ds2786_battery_external_power_changed;	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;	di->update_time=0;	retval = power_supply_register(&pdev->dev, &di->bat);	if (retval)	{		dev_err(di->dev, "failed to register battery\n");		goto batt_failed;	}	INIT_DELAYED_WORK(&di->monitor_work, ds2786_battery_work);	di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);	if (!di->monitor_wqueue)	{		retval = -ESRCH;		goto workqueue_failed;	}	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);	request_irq(IRQ_EINT3,pwr_chang_irq,0,"PWR_MON",0);	//s3c_irqext_type(IRQ_EINT3,0x03);	goto success;workqueue_failed:	power_supply_unregister(&di->bat);batt_failed:	kfree(di);	printk(KERN_ALERT"there is no DS2786\n");di_alloc_failed:success:	return retval;}static int ds2786_battery_remove(struct platform_device *pdev){	struct ds2786_device_info *di = platform_get_drvdata(pdev);	cancel_rearming_delayed_workqueue(di->monitor_wqueue,					  &di->monitor_work);	destroy_workqueue(di->monitor_wqueue);	power_supply_unregister(&di->bat);	i2c_del_driver(&di->ds2786_driver);	return 0;}#ifdef CONFIG_PMstatic int ds2786_battery_suspend(struct platform_device *pdev,				  pm_message_t state){	struct ds2786_device_info *di = platform_get_drvdata(pdev);	cancel_delayed_work(&di->monitor_work);	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;	printk(KERN_ALERT"ds2786_battery_suspend\n");	return 0;}static int ds2786_battery_resume(struct platform_device *pdev){	struct ds2786_device_info *di = platform_get_drvdata(pdev);	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;	power_supply_changed(&di->bat);	//cancel_delayed_work(&di->monitor_work);	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ*60);	printk(KERN_ALERT"ds2786_battery_resume\n");	return 0;}#else#define ds2786_battery_suspend NULL#define ds2786_battery_resume NULL#endif /* CONFIG_PM */static struct platform_driver ds2786_battery_driver = {	.driver = {		.name = "ds2786-battery",	},	.probe	  = ds2786_battery_probe,	.remove   = ds2786_battery_remove,	.suspend  = ds2786_battery_suspend,	.resume	  = ds2786_battery_resume,};static int __init ds2786_battery_init(void){	return platform_driver_register(&ds2786_battery_driver);}static void __exit ds2786_battery_exit(void){	platform_driver_unregister(&ds2786_battery_driver);}module_init(ds2786_battery_init);module_exit(ds2786_battery_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "	      "Matt Reimer <mreimer@vpop.net>, "	      "Anton Vorontsov <cbou@mail.ru>");MODULE_DESCRIPTION("ds2760 battery driver");//end of apm part

⌨️ 快捷键说明

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