Lines Matching refs:cw_bat

85 static int cw_read_word(struct cw_battery *cw_bat, u8 reg, u16 *val)  in cw_read_word()  argument
90 ret = regmap_bulk_read(cw_bat->regmap, reg, &value, sizeof(value)); in cw_read_word()
98 static int cw_update_profile(struct cw_battery *cw_bat) in cw_update_profile() argument
105 ret = regmap_read(cw_bat->regmap, CW2015_REG_MODE, &reg_val); in cw_update_profile()
111 dev_err(cw_bat->dev, in cw_update_profile()
117 ret = regmap_raw_write(cw_bat->regmap, CW2015_REG_BATINFO, in cw_update_profile()
118 cw_bat->bat_profile, in cw_update_profile()
126 reg_val |= CW2015_ATHD(cw_bat->alert_level); in cw_update_profile()
127 ret = regmap_write(cw_bat->regmap, CW2015_REG_CONFIG, reg_val); in cw_update_profile()
134 ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reg_val); in cw_update_profile()
142 ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val); in cw_update_profile()
147 ret = regmap_read_poll_timeout(cw_bat->regmap, CW2015_REG_SOC, in cw_update_profile()
151 dev_err(cw_bat->dev, in cw_update_profile()
154 dev_dbg(cw_bat->dev, "Battery profile updated\n"); in cw_update_profile()
159 static int cw_init(struct cw_battery *cw_bat) in cw_init() argument
166 ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reg_val); in cw_init()
171 ret = regmap_read(cw_bat->regmap, CW2015_REG_CONFIG, &reg_val); in cw_init()
175 if ((reg_val & CW2015_MASK_ATHD) != CW2015_ATHD(cw_bat->alert_level)) { in cw_init()
176 dev_dbg(cw_bat->dev, "Setting new alert level\n"); in cw_init()
178 reg_val |= ~CW2015_ATHD(cw_bat->alert_level); in cw_init()
179 ret = regmap_write(cw_bat->regmap, CW2015_REG_CONFIG, reg_val); in cw_init()
184 ret = regmap_read(cw_bat->regmap, CW2015_REG_CONFIG, &reg_val); in cw_init()
189 dev_dbg(cw_bat->dev, in cw_init()
191 if (cw_bat->bat_profile) { in cw_init()
192 ret = cw_update_profile(cw_bat); in cw_init()
194 dev_err(cw_bat->dev, in cw_init()
199 dev_warn(cw_bat->dev, in cw_init()
202 } else if (cw_bat->bat_profile) { in cw_init()
205 ret = regmap_raw_read(cw_bat->regmap, CW2015_REG_BATINFO, in cw_init()
208 dev_err(cw_bat->dev, in cw_init()
213 if (memcmp(bat_info, cw_bat->bat_profile, CW2015_SIZE_BATINFO)) { in cw_init()
214 dev_warn(cw_bat->dev, "Replacing stored battery profile\n"); in cw_init()
215 ret = cw_update_profile(cw_bat); in cw_init()
220 dev_warn(cw_bat->dev, in cw_init()
224 dev_dbg(cw_bat->dev, "Battery profile configured\n"); in cw_init()
228 static int cw_power_on_reset(struct cw_battery *cw_bat) in cw_power_on_reset() argument
234 ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val); in cw_power_on_reset()
242 ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val); in cw_power_on_reset()
246 ret = cw_init(cw_bat); in cw_power_on_reset()
255 static int cw_get_soc(struct cw_battery *cw_bat) in cw_get_soc() argument
260 ret = regmap_read(cw_bat->regmap, CW2015_REG_SOC, &soc); in cw_get_soc()
266 CW2015_BAT_SOC_ERROR_MS / cw_bat->poll_interval_ms; in cw_get_soc()
268 dev_err(cw_bat->dev, "Invalid SoC %d%%\n", soc); in cw_get_soc()
269 cw_bat->read_errors++; in cw_get_soc()
270 if (cw_bat->read_errors > max_error_cycles) { in cw_get_soc()
271 dev_warn(cw_bat->dev, in cw_get_soc()
273 cw_power_on_reset(cw_bat); in cw_get_soc()
274 cw_bat->read_errors = 0; in cw_get_soc()
276 return cw_bat->soc; in cw_get_soc()
278 cw_bat->read_errors = 0; in cw_get_soc()
281 if (cw_bat->status == POWER_SUPPLY_STATUS_CHARGING && soc == cw_bat->soc) { in cw_get_soc()
283 CW2015_BAT_CHARGING_STUCK_MS / cw_bat->poll_interval_ms; in cw_get_soc()
285 cw_bat->charge_stuck_cnt++; in cw_get_soc()
286 if (cw_bat->charge_stuck_cnt > max_stuck_cycles) { in cw_get_soc()
287 dev_warn(cw_bat->dev, in cw_get_soc()
289 cw_power_on_reset(cw_bat); in cw_get_soc()
290 cw_bat->charge_stuck_cnt = 0; in cw_get_soc()
293 cw_bat->charge_stuck_cnt = 0; in cw_get_soc()
297 if (cw_bat->charger_attached && HYSTERESIS(soc, cw_bat->soc, 0, 3)) in cw_get_soc()
298 soc = cw_bat->soc; in cw_get_soc()
301 if (!cw_bat->charger_attached && HYSTERESIS(soc, cw_bat->soc, 3, 0)) in cw_get_soc()
302 soc = cw_bat->soc; in cw_get_soc()
307 static int cw_get_voltage(struct cw_battery *cw_bat) in cw_get_voltage() argument
314 ret = cw_read_word(cw_bat, CW2015_REG_VCELL, &reg_val); in cw_get_voltage()
328 if (cw_bat->dual_cell) in cw_get_voltage()
331 dev_dbg(cw_bat->dev, "Read voltage: %d mV, raw=0x%04x\n", in cw_get_voltage()
336 static int cw_get_time_to_empty(struct cw_battery *cw_bat) in cw_get_time_to_empty() argument
341 ret = cw_read_word(cw_bat, CW2015_REG_RRT_ALERT, &value16); in cw_get_time_to_empty()
348 static void cw_update_charge_status(struct cw_battery *cw_bat) in cw_update_charge_status() argument
352 ret = power_supply_am_i_supplied(cw_bat->rk_bat); in cw_update_charge_status()
354 dev_warn(cw_bat->dev, "Failed to get supply state: %d\n", ret); in cw_update_charge_status()
359 if (cw_bat->charger_attached != charger_attached) { in cw_update_charge_status()
360 cw_bat->battery_changed = true; in cw_update_charge_status()
362 cw_bat->charge_count++; in cw_update_charge_status()
364 cw_bat->charger_attached = charger_attached; in cw_update_charge_status()
368 static void cw_update_soc(struct cw_battery *cw_bat) in cw_update_soc() argument
372 soc = cw_get_soc(cw_bat); in cw_update_soc()
374 dev_err(cw_bat->dev, "Failed to get SoC from gauge: %d\n", soc); in cw_update_soc()
375 else if (cw_bat->soc != soc) { in cw_update_soc()
376 cw_bat->soc = soc; in cw_update_soc()
377 cw_bat->battery_changed = true; in cw_update_soc()
381 static void cw_update_voltage(struct cw_battery *cw_bat) in cw_update_voltage() argument
385 voltage_mv = cw_get_voltage(cw_bat); in cw_update_voltage()
387 dev_err(cw_bat->dev, "Failed to get voltage from gauge: %d\n", in cw_update_voltage()
390 cw_bat->voltage_mv = voltage_mv; in cw_update_voltage()
393 static void cw_update_status(struct cw_battery *cw_bat) in cw_update_status() argument
397 if (cw_bat->charger_attached) { in cw_update_status()
398 if (cw_bat->soc >= 100) in cw_update_status()
404 if (cw_bat->status != status) in cw_update_status()
405 cw_bat->battery_changed = true; in cw_update_status()
406 cw_bat->status = status; in cw_update_status()
409 static void cw_update_time_to_empty(struct cw_battery *cw_bat) in cw_update_time_to_empty() argument
413 time_to_empty = cw_get_time_to_empty(cw_bat); in cw_update_time_to_empty()
415 dev_err(cw_bat->dev, "Failed to get time to empty from gauge: %d\n", in cw_update_time_to_empty()
419 cw_bat->time_to_empty = time_to_empty; in cw_update_time_to_empty()
425 struct cw_battery *cw_bat; in cw_bat_work() local
430 cw_bat = container_of(delay_work, struct cw_battery, battery_delay_work); in cw_bat_work()
431 ret = regmap_read(cw_bat->regmap, CW2015_REG_MODE, &reg_val); in cw_bat_work()
433 dev_err(cw_bat->dev, "Failed to read mode from gauge: %d\n", ret); in cw_bat_work()
439 if (!cw_power_on_reset(cw_bat)) in cw_bat_work()
443 cw_update_soc(cw_bat); in cw_bat_work()
444 cw_update_voltage(cw_bat); in cw_bat_work()
445 cw_update_charge_status(cw_bat); in cw_bat_work()
446 cw_update_status(cw_bat); in cw_bat_work()
447 cw_update_time_to_empty(cw_bat); in cw_bat_work()
449 dev_dbg(cw_bat->dev, "charger_attached = %d\n", cw_bat->charger_attached); in cw_bat_work()
450 dev_dbg(cw_bat->dev, "status = %d\n", cw_bat->status); in cw_bat_work()
451 dev_dbg(cw_bat->dev, "soc = %d%%\n", cw_bat->soc); in cw_bat_work()
452 dev_dbg(cw_bat->dev, "voltage = %dmV\n", cw_bat->voltage_mv); in cw_bat_work()
454 if (cw_bat->battery_changed) in cw_bat_work()
455 power_supply_changed(cw_bat->rk_bat); in cw_bat_work()
456 cw_bat->battery_changed = false; in cw_bat_work()
458 queue_delayed_work(cw_bat->battery_workqueue, in cw_bat_work()
459 &cw_bat->battery_delay_work, in cw_bat_work()
460 msecs_to_jiffies(cw_bat->poll_interval_ms)); in cw_bat_work()
463 static bool cw_battery_valid_time_to_empty(struct cw_battery *cw_bat) in cw_battery_valid_time_to_empty() argument
465 return cw_bat->time_to_empty > 0 && in cw_battery_valid_time_to_empty()
466 cw_bat->time_to_empty < CW2015_MASK_SOC && in cw_battery_valid_time_to_empty()
467 cw_bat->status == POWER_SUPPLY_STATUS_DISCHARGING; in cw_battery_valid_time_to_empty()
470 static int cw_get_capacity_leve(struct cw_battery *cw_bat) in cw_get_capacity_leve() argument
472 if (cw_bat->soc < 1) in cw_get_capacity_leve()
474 else if (cw_bat->soc <= 20) in cw_get_capacity_leve()
476 else if (cw_bat->soc <= 70) in cw_get_capacity_leve()
478 else if (cw_bat->soc <= 90) in cw_get_capacity_leve()
488 struct cw_battery *cw_bat; in cw_battery_get_property() local
490 cw_bat = power_supply_get_drvdata(psy); in cw_battery_get_property()
493 val->intval = cw_bat->soc; in cw_battery_get_property()
497 val->intval = cw_get_capacity_leve(cw_bat); in cw_battery_get_property()
501 val->intval = cw_bat->status; in cw_battery_get_property()
505 val->intval = !!cw_bat->voltage_mv; in cw_battery_get_property()
509 val->intval = cw_bat->voltage_mv * 1000; in cw_battery_get_property()
513 if (cw_battery_valid_time_to_empty(cw_bat)) in cw_battery_get_property()
514 val->intval = cw_bat->time_to_empty; in cw_battery_get_property()
524 val->intval = cw_bat->charge_count; in cw_battery_get_property()
529 if (cw_bat->battery.charge_full_design_uah > 0) in cw_battery_get_property()
530 val->intval = cw_bat->battery.charge_full_design_uah; in cw_battery_get_property()
536 if (cw_battery_valid_time_to_empty(cw_bat) && in cw_battery_get_property()
537 cw_bat->battery.charge_full_design_uah > 0) { in cw_battery_get_property()
539 val->intval = cw_bat->battery.charge_full_design_uah; in cw_battery_get_property()
540 val->intval = val->intval * cw_bat->soc / 100; in cw_battery_get_property()
543 val->intval = 60 * val->intval / cw_bat->time_to_empty; in cw_battery_get_property()
578 static int cw2015_parse_properties(struct cw_battery *cw_bat) in cw2015_parse_properties() argument
580 struct device *dev = cw_bat->dev; in cw2015_parse_properties()
586 dev_warn(cw_bat->dev, in cw2015_parse_properties()
589 dev_err(cw_bat->dev, "battery-profile must be %d bytes\n", in cw2015_parse_properties()
593 cw_bat->bat_profile = devm_kzalloc(dev, length, GFP_KERNEL); in cw2015_parse_properties()
594 if (!cw_bat->bat_profile) in cw2015_parse_properties()
599 cw_bat->bat_profile, in cw2015_parse_properties()
605 cw_bat->dual_cell = device_property_read_bool(dev, "cellwise,dual-cell"); in cw2015_parse_properties()
608 &cw_bat->poll_interval_ms); in cw2015_parse_properties()
610 dev_dbg(cw_bat->dev, "Using default poll interval\n"); in cw2015_parse_properties()
611 cw_bat->poll_interval_ms = CW2015_DEFAULT_POLL_INTERVAL_MS; in cw2015_parse_properties()
663 struct cw_battery *cw_bat; in cw_bat_probe() local
666 cw_bat = devm_kzalloc(&client->dev, sizeof(*cw_bat), GFP_KERNEL); in cw_bat_probe()
667 if (!cw_bat) in cw_bat_probe()
670 i2c_set_clientdata(client, cw_bat); in cw_bat_probe()
671 cw_bat->dev = &client->dev; in cw_bat_probe()
672 cw_bat->soc = 1; in cw_bat_probe()
674 ret = cw2015_parse_properties(cw_bat); in cw_bat_probe()
676 dev_err(cw_bat->dev, "Failed to parse cw2015 properties\n"); in cw_bat_probe()
680 cw_bat->regmap = devm_regmap_init_i2c(client, &cw2015_regmap_config); in cw_bat_probe()
681 if (IS_ERR(cw_bat->regmap)) { in cw_bat_probe()
682 dev_err(cw_bat->dev, "Failed to allocate regmap: %ld\n", in cw_bat_probe()
683 PTR_ERR(cw_bat->regmap)); in cw_bat_probe()
684 return PTR_ERR(cw_bat->regmap); in cw_bat_probe()
687 ret = cw_init(cw_bat); in cw_bat_probe()
689 dev_err(cw_bat->dev, "Init failed: %d\n", ret); in cw_bat_probe()
693 psy_cfg.drv_data = cw_bat; in cw_bat_probe()
694 psy_cfg.fwnode = dev_fwnode(cw_bat->dev); in cw_bat_probe()
696 cw_bat->rk_bat = devm_power_supply_register(&client->dev, in cw_bat_probe()
699 if (IS_ERR(cw_bat->rk_bat)) { in cw_bat_probe()
701 dev_err_probe(&client->dev, PTR_ERR(cw_bat->rk_bat), in cw_bat_probe()
703 return PTR_ERR(cw_bat->rk_bat); in cw_bat_probe()
706 ret = power_supply_get_battery_info(cw_bat->rk_bat, &cw_bat->battery); in cw_bat_probe()
708 dev_warn(cw_bat->dev, in cw_bat_probe()
712 cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery"); in cw_bat_probe()
713 INIT_DELAYED_WORK(&cw_bat->battery_delay_work, cw_bat_work); in cw_bat_probe()
714 queue_delayed_work(cw_bat->battery_workqueue, in cw_bat_probe()
715 &cw_bat->battery_delay_work, msecs_to_jiffies(10)); in cw_bat_probe()
722 struct cw_battery *cw_bat = i2c_get_clientdata(client); in cw_bat_suspend() local
724 cancel_delayed_work_sync(&cw_bat->battery_delay_work); in cw_bat_suspend()
731 struct cw_battery *cw_bat = i2c_get_clientdata(client); in cw_bat_resume() local
733 queue_delayed_work(cw_bat->battery_workqueue, in cw_bat_resume()
734 &cw_bat->battery_delay_work, 0); in cw_bat_resume()
742 struct cw_battery *cw_bat = i2c_get_clientdata(client); in cw_bat_remove() local
744 cancel_delayed_work_sync(&cw_bat->battery_delay_work); in cw_bat_remove()
745 power_supply_put_battery_info(cw_bat->rk_bat, &cw_bat->battery); in cw_bat_remove()