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; }
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; }
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; }
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; }
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; }
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; }