コード例 #1
0
ファイル: pmic_battery.c プロジェクト: AvalueAES/rev-sa01
static int mc13892_charger_update_status(struct mc13892_dev_info *di)
{
	int ret;
	unsigned int value;
	int online;

	ret = pmic_read_reg(REG_INT_SENSE0, &value, BITFMASK(BIT_CHG_DETS));

	if (ret == 0) {
		online = BITFEXT(value, BIT_CHG_DETS);
		if (online != di->charger_online) {
			di->charger_online = online;
			dev_info(di->charger.dev, "charger status: %s\n",
				online ? "online" : "offline");
			power_supply_changed(&di->charger);

			cancel_delayed_work(&di->monitor_work);
			queue_delayed_work(di->monitor_wqueue,
				&di->monitor_work, HZ / 10);
			if (online) {
				pmic_start_coulomb_counter();
				pmic_restart_charging();
				queue_delayed_work(chg_wq, &chg_work, 100);
				chg_wa_timer = 1;
			} else {
				cancel_delayed_work(&chg_work);
				chg_wa_timer = 0;
				pmic_stop_coulomb_counter();
		}
	}
	}

	return ret;
}
コード例 #2
0
ファイル: pmic_battery.c プロジェクト: pocketbook/801
static int pmic_battery_probe(struct platform_device *pdev)
{
	int retval = 0;
	struct mc13892_dev_info *di;
	pmic_event_callback_t bat_event_callback;
	pmic_version_t pmic_version;

	//printk("%s %s %d   \n",__FILE__,__func__,__LINE__); 

	/* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */
	pmic_version = pmic_get_version();
	if (pmic_version.revision < 20) {
		pr_debug("Battery driver is only applied for MC13892 V2.0\n");
		return -1;
	}
	if (machine_is_mx50_arm2()) {
		pr_debug("mc13892 charger is not used for this platform\n");
		return -1;
	}

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di) {
		retval = -ENOMEM;
		goto di_alloc_failed;
	}

	di->init_charge = -1;

	platform_set_drvdata(pdev, di);
   
	di->charger.name	= "mc13892_charger";
	di->charger.type = POWER_SUPPLY_TYPE_MAINS;
	di->charger.properties = mc13892_charger_props;
	di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props);
	di->charger.get_property = mc13892_charger_get_property;
	retval = power_supply_register(&pdev->dev, &di->charger);
	if (retval) {
		dev_err(di->dev, "failed to register charger\n");
		goto charger_failed;
	}

	INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work);
	
	di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
	if (!di->monitor_wqueue) {
		retval = -ESRCH;
		goto workqueue_failed;
	}
	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10);
	//queue_delayed_work(di->monitor_wqueue, &di->monitor_work, msecs_to_jiffies(10000));

	pmic_stop_coulomb_counter();
	pmic_calibrate_coulomb_counter();

	//for get correct voltage on the battery when booting with external power.
	//chg_thread will change it, when next work (chg_work) is start.
	pmic_set_chg_current(0);
	INIT_DELAYED_WORK(&di->calc_capacity,mc13892_compute_battery_capacity_from_CC);
	queue_delayed_work(di->monitor_wqueue, &di->calc_capacity, 0);

	INIT_DELAYED_WORK(&chg_work, chg_thread);
	chg_wq = create_singlethread_workqueue("mxc_chg");
	if (!chg_wq) {
		retval = -ESRCH;
		goto workqueue_failed;
	}
	queue_delayed_work(chg_wq, &chg_work, HZ);

	di->dev	= &pdev->dev;
	di->bat.name	= "mc13892_bat";
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = mc13892_battery_props;
	di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props);
	di->bat.get_property = mc13892_battery_get_property;
	di->bat.use_for_apm = 1;

	di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
	//di->battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 


	retval = power_supply_register(&pdev->dev, &di->bat);
	if (retval) {
		dev_err(di->dev, "failed to register battery\n");
		goto batt_failed;
	}

   


	bat_event_callback.func = charger_online_event_callback;
	bat_event_callback.param = (void *) di;
	pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback);

	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr);
	if (retval) {
		printk(KERN_ERR
		       "Battery: Unable to register sysdev entry for Battery");
		goto workqueue_failed;
	}
	
	chg_wa_is_active = 1;
	chg_wa_timer = 0;
	disable_chg_timer = 0;

#if defined(PMIC_MC13892_BATTERY_WORK)
      work_init();
#endif
	
	goto success;

workqueue_failed:
	power_supply_unregister(&di->charger);
charger_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	kfree(di);
di_alloc_failed:
success:
	dev_dbg(di->dev, "%s battery probed!\n", __func__);
	return retval;


	return 0;
}
コード例 #3
0
ファイル: pmic_battery.c プロジェクト: pocketbook/801
static int mc13892_compute_battery_capacity_from_CC(struct work_struct *work) 
{
	int v=0;
	static int old_state = -1;
	//static int old_init_charge = 0;
	int CurVolts =0;
	int iCount=0;
	int  CurRangeNextC =0;
	int  CurRangeC =0;
	int CurCountNext = 0;
	int CurCountPre = 0;
	static int old_CurRangeC = 0;
	long cc = 0;

	struct mc13892_dev_info *di = container_of(work, struct mc13892_dev_info, calc_capacity.work);

	if (di->charger_online != old_state) {
		//pmic_calibrate_coulomb_counter();
		pmic_stop_coulomb_counter();
		di->init_charge = -1;

	}

	if (di->init_charge == -1) 
	{ /*first entry - init */
		//pmic_set_chg_current(0);
		mc13892_battery_read_status(di);
		//printk("[%s] di->voltage_uV = %i; %i\n",__func__,di->voltage_uV,di->voltage_uV/1000);
		di->init_charge = mc13892_compute_battery_charge_from_V(di->voltage_uV / 1000);
		pmic_start_coulomb_counter();
		//mc13892_battery_read_status(di);
	}

	old_state = di->charger_online;


	pmic_get_charger_coulomb_raw(&cc);

	if (di->charger_online) {
		v = (di->init_charge + ((long)abs(cc) * 10 / 36)) * 100 /  BAT_CAP_MAH;
	} else {
		v = (di->init_charge - ((long)abs(0xffff - cc ? cc : 0xffff) * 10 / 36)) * 100 /  BAT_CAP_MAH;
	}


	if(bUsbstateChanged)
	{
		bUsbstateChanged = false;
		capacityOffset = v - di->capacity;
	}

	v=v -capacityOffset;

	///Bootup with DC-DC,sometimes the capacity read error,so we
	///need reread again.
	if((di->charger_online) && bBootupWithCharger){
		CurVolts =(di->voltage_uV / 1000) ;
		while (CurVolts < charge[iCount].v) {
			CurCountNext = iCount+1;
			CurRangeNextC = charge[CurCountNext].c;
			CurRangeC  = charge[iCount].c;
			iCount++;
		}

		if(( v > CurRangeC ) 
			||  (v< CurRangeNextC) 
			)
		{
			di->init_charge = -1;
			if (di->monitor_wqueue)
				queue_delayed_work(di->monitor_wqueue, &di->calc_capacity, msecs_to_jiffies(50));
			else
				schedule_delayed_work(&di->calc_capacity, msecs_to_jiffies(50));
		}
		if(v< old_CurRangeC){
			v= old_CurRangeC;
		}else{
			old_CurRangeC =v;
		}
	}

	if (v > 100) v = 100;
	if (v < 0) v = 0;
	di->capacity = v;

	////sometimes when the voltage is low 3600,
	///the capacity will be read error. it as 100,so we use the
	///follow funtions to avoid it.
	if(!(di->charger_online)){
		if(((di->voltage_uV / 1000) < 3550)
			&& ((di->voltage_uV / 1000) > 3525))
		{
			if(di->capacity > 5)
				di->capacity = 4;

		}else if (((di->voltage_uV / 1000) < 3525)
			&& ((di->voltage_uV / 1000) > 3500))
		{
			if(di->capacity > 2)
			   di->capacity = 2;
		}else if ((di->voltage_uV / 1000) < 3500)
		{
			di->capacity = 0;
		}
	}

	if (di->monitor_wqueue)
		queue_delayed_work(di->monitor_wqueue, &di->calc_capacity, msecs_to_jiffies(5000));
	else
		schedule_delayed_work(&di->calc_capacity, msecs_to_jiffies(5000));
	return 0;
}
コード例 #4
0
ファイル: pmic_battery.c プロジェクト: AvalueAES/rev-sa01
static int pmic_battery_probe(struct platform_device *pdev)
{
	int retval = 0;
	struct mc13892_dev_info *di;
	pmic_event_callback_t bat_event_callback;
	pmic_version_t pmic_version;

	/* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */
	pmic_version = pmic_get_version();
	if (pmic_version.revision < 20) {
		pr_debug("Battery driver is only applied for MC13892 V2.0\n");
		return -1;
	}
	if (machine_is_mx50_arm2()) {
		pr_debug("mc13892 charger is not used for this platform\n");
		return -1;
	}

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di) {
		retval = -ENOMEM;
		goto di_alloc_failed;
	}

	platform_set_drvdata(pdev, di);

	di->charger.name	= "mc13892_charger";
	di->charger.type = POWER_SUPPLY_TYPE_MAINS;
	di->charger.properties = mc13892_charger_props;
	di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props);
	di->charger.get_property = mc13892_charger_get_property;
	retval = power_supply_register(&pdev->dev, &di->charger);
	if (retval) {
		dev_err(di->dev, "failed to register charger\n");
		goto charger_failed;
	}

	INIT_DELAYED_WORK(&chg_work, chg_thread);
	chg_wq = create_singlethread_workqueue("mxc_chg");
	if (!chg_wq) {
		retval = -ESRCH;
		goto workqueue_failed;
	}

	INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work);
	di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
	if (!di->monitor_wqueue) {
		retval = -ESRCH;
		goto workqueue_failed;
	}
	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10);

	di->dev	= &pdev->dev;
	di->bat.name	= "mc13892_bat";
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = mc13892_battery_props;
	di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props);
	di->bat.get_property = mc13892_battery_get_property;
	di->bat.use_for_apm = 1;

	di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;

	retval = power_supply_register(&pdev->dev, &di->bat);
	if (retval) {
		dev_err(di->dev, "failed to register battery\n");
		goto batt_failed;
	}

	bat_event_callback.func = charger_online_event_callback;
	bat_event_callback.param = (void *) di;
	pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback);
	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr);

	if (retval) {
		printk(KERN_ERR
		       "Battery: Unable to register sysdev entry for Battery");
		goto workqueue_failed;
	}
	chg_wa_is_active = 1;
	chg_wa_timer = 0;
	disable_chg_timer = 0;

	pmic_stop_coulomb_counter();
	pmic_calibrate_coulomb_counter();
	goto success;

workqueue_failed:
	power_supply_unregister(&di->charger);
charger_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	kfree(di);
di_alloc_failed:
success:
	dev_dbg(di->dev, "%s battery probed!\n", __func__);
	return retval;


	return 0;
}
コード例 #5
0
static int mc13892_charger_update_status(struct mc13892_dev_info *di)
{
	int ret;
#ifndef CONFIG_MACH_MX51_ERDOS
	unsigned int value;
#endif /* CONFIG_MACH_MX51_ERDOS */
	int online;

#ifdef CONFIG_MACH_MX51_ERDOS
	ret = pmic_get_dcinput_voltage ((unsigned short *)0);
	if (ret == 0) {
		online = 1;
	} else if (ret == 1) {
		online = 0;
	} else {
		online = di->charger_online;	/* keep previous */
	}
	ret = 0;
		/*
	 * Battery/DCinput update
		 */
		if (online == 1) {
			gpio_battery_enable ( 0 );
	} else if (online == 0) {
			gpio_battery_enable ( 1 );
		}
	if (online != di->charger_online) {
		di->charger_online = online;
		/*
		 * check power_supply_register.
		 */
		if (di->charger.dev != 0) {
		dev_info(di->charger.dev, "charger status: %s\n",
			online ? "online" : "offline");
		power_supply_changed(&di->charger);
		} else {
			printk ("mc13892_charger_update_status: charger status: %s\n",
				online ? "online" : "offline");
		}
	}
#else
	ret = pmic_read_reg(REG_INT_SENSE0, &value, BITFMASK(BIT_CHG_DETS));

	if (ret == 0) {
		online = BITFEXT(value, BIT_CHG_DETS);
		if (online != di->charger_online) {
			di->charger_online = online;
			dev_info(di->charger.dev, "charger status: %s\n",
				online ? "online" : "offline");
			power_supply_changed(&di->charger);

			cancel_delayed_work(&di->monitor_work);
			queue_delayed_work(di->monitor_wqueue,
				&di->monitor_work, HZ / 10);
			if (online) {
				pmic_start_coulomb_counter();
				pmic_restart_charging();
			} else
				pmic_stop_coulomb_counter();
		}
	}
#endif /* CONFIG_MACH_MX51_ERDOS */

	return ret;
}
コード例 #6
0
static int pmic_battery_probe(struct platform_device *pdev)
{
	int retval = 0;
	struct mc13892_dev_info *di;
#ifndef CONFIG_MACH_MX51_ERDOS
	pmic_event_callback_t bat_event_callback;
#endif /* CONFIG_MACH_MX51_ERDOS */
	pmic_version_t pmic_version;

	/* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */
	pmic_version = pmic_get_version();
	if (pmic_version.revision < 20) {
		pr_debug("Battery driver is only applied for MC13892 V2.0\n");
		return -1;
	}

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di) {
		retval = -ENOMEM;
		goto di_alloc_failed;
	}

	platform_set_drvdata(pdev, di);

	di->dev	= &pdev->dev;
	di->bat.name	= "mc13892_bat";
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = mc13892_battery_props;
	di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props);
	di->bat.get_property = mc13892_battery_get_property;

	di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;

	retval = power_supply_register(&pdev->dev, &di->bat);
	if (retval) {
		dev_err(di->dev, "failed to register battery\n");
		goto batt_failed;
	}
	di->charger.name	= "mc13892_charger";
	di->charger.type = POWER_SUPPLY_TYPE_MAINS;
	di->charger.properties = mc13892_charger_props;
	di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props);
	di->charger.get_property = mc13892_charger_get_property;
	retval = power_supply_register(&pdev->dev, &di->charger);
	if (retval) {
		dev_err(di->dev, "failed to register charger\n");
		goto charger_failed;
	}
	INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work);
	di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
	if (!di->monitor_wqueue) {
		retval = -ESRCH;
		goto workqueue_failed;
	}
	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10);

#ifdef CONFIG_MACH_MX51_ERDOS
#ifdef ALWAY_REFON
	gpio_refon(1);		// select measurement
#endif /* ALWAY_REFON */
	/*
	 * initial value (BATT voltage raw)
	 */
#ifdef CONFIG_PROC_FS
	proc_create ("battery", 0, NULL, &battery_proc_fops);
#endif /* CONFIG_PROC_FS */
	battery_low_init (di);
#else
	bat_event_callback.func = charger_online_event_callback;
	bat_event_callback.param = (void *) di;
	pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback);

	pmic_stop_coulomb_counter();
	pmic_calibrate_coulomb_counter();
#endif /* CONFIG_MACH_MX51_ERDOS */
	goto success;

workqueue_failed:
	power_supply_unregister(&di->charger);
charger_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	kfree(di);
di_alloc_failed:
success:
	dev_dbg(di->dev, "%s battery probed!\n", __func__);
	return retval;


	return 0;
}