Lines Matching +full:vbus +full:- +full:divider
1 // SPDX-License-Identifier: GPL-2.0-only
10 * Copyright (C) 2009-2010 Motorola, Inc.
23 #include <linux/nvmem-consumer.h>
28 #include <linux/mfd/motorola-cpcap.h>
32 * map to MC13783UG.pdf "Table 5-19. Register 13, Power Control 0"
141 #define CPCAP_NO_BATTERY -400
153 return &ddata->state[state];
186 channel = ddata->channels[CPCAP_BATTERY_IIO_BATTDET];
190 dev_warn(ddata->dev, "%s failed: %i\n", __func__, error);
206 channel = ddata->channels[CPCAP_BATTERY_IIO_VOLTAGE];
209 dev_warn(ddata->dev, "%s failed: %i\n", __func__, error);
222 channel = ddata->channels[CPCAP_BATTERY_IIO_BATT_CURRENT];
225 dev_warn(ddata->dev, "%s failed: %i\n", __func__, error);
234 * cpcap_battery_cc_raw_div - calculate and divide coulomb counter μAms values
239 * @divider: conversion divider
256 s16 offset, u32 divider)
260 if (!divider)
264 acc -= (s64)sample * offset;
265 acc *= ddata->cc_lsb;
266 acc *= -1;
267 acc = div_s64(acc, divider);
293 * cpcap_battery_read_accumulated - reads cpcap coulomb counter
314 ccd->sample = 0;
315 ccd->accumulator = 0;
316 ccd->offset = 0;
317 ccd->integrator = 0;
320 error = regmap_bulk_read(ddata->reg, CPCAP_REG_CCS1,
326 ccd->sample = (buf[1] & 0x0fff) << 16;
327 ccd->sample |= buf[0];
328 if (ddata->vendor == CPCAP_VENDOR_TI)
329 ccd->sample = sign_extend32(24, ccd->sample);
332 ccd->accumulator = ((s16)buf[3]) << 16;
333 ccd->accumulator |= buf[2];
339 ccd->offset = buf[4];
340 ccd->offset = sign_extend32(ccd->offset, 9);
343 if (ddata->vendor == CPCAP_VENDOR_TI)
344 ccd->integrator = sign_extend32(buf[6], 13);
346 ccd->integrator = (s16)buf[6];
349 ccd->sample,
350 ccd->accumulator,
351 ccd->offset);
401 if (strcmp(dev_name(dev), "89-500029ba0f73") == 0)
412 ddata->check_nvmem = false;
416 ddata->check_nvmem = true;
417 dev_info_once(ddata->dev, "Can not find battery nvmem device. Assuming generic lipo battery\n");
420 ddata->check_nvmem = true;
421 dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n");
426 ddata->config = cpcap_battery_eb41_data;
429 ddata->config = cpcap_battery_bw8x_data;
432 ddata->config = cpcap_battery_unkown_data;
437 * cpcap_battery_cc_get_avg_current - read cpcap coulumb counter
447 error = regmap_read(ddata->reg, CPCAP_REG_CCI, &value);
451 if (ddata->vendor == CPCAP_VENDOR_TI) {
460 error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value);
478 return -ENODEV;
502 dev_dbg(ddata->dev, "charger disconnected\n");
503 ddata->is_full = 0;
506 dev_dbg(ddata->dev, "charger full status\n");
507 ddata->is_full = 1;
519 vfull = ddata->config.bat.constant_charge_voltage_max_uv - 120000;
521 if (ddata->is_full && state->voltage < vfull)
522 ddata->is_full = 0;
524 return ddata->is_full;
532 if (state->current_ua > 0 && (state->voltage <= 3350000 || is_low))
552 s64 delta_ms = ktime_to_ms(ktime_sub(now, latest->time));
577 if (empty->voltage && empty->voltage != -1) {
578 empty->voltage = -1;
579 ddata->charge_full =
580 empty->counter_uah - full->counter_uah;
581 } else if (ddata->charge_full) {
582 empty->voltage = -1;
583 empty->counter_uah =
584 full->counter_uah + ddata->charge_full;
591 if (full->voltage) {
592 full->voltage = 0;
593 ddata->charge_full =
594 empty->counter_uah - full->counter_uah;
602 * Update battery status when cpcap-charger calls power_supply_changed().
653 if (ddata->check_nvmem)
658 if (latest->temperature > CPCAP_NO_BATTERY || ignore_temperature_probe)
659 val->intval = 1;
661 val->intval = 0;
665 val->intval = POWER_SUPPLY_STATUS_FULL;
669 val->intval = POWER_SUPPLY_STATUS_CHARGING;
671 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
674 val->intval = ddata->config.info.technology;
677 val->intval = cpcap_battery_get_voltage(ddata);
680 val->intval = ddata->config.info.voltage_max_design;
683 val->intval = ddata->config.info.voltage_min_design;
686 val->intval = ddata->config.bat.constant_charge_voltage_max_uv;
689 sample = latest->cc.sample - previous->cc.sample;
691 val->intval = cpcap_battery_cc_get_avg_current(ddata);
694 accumulator = latest->cc.accumulator - previous->cc.accumulator;
695 val->intval = cpcap_battery_cc_to_ua(ddata, sample,
697 latest->cc.offset);
700 val->intval = latest->current_ua;
703 val->intval = latest->counter_uah;
706 tmp = (latest->voltage / 10000) * latest->current_ua;
707 val->intval = div64_s64(tmp, 100);
710 sample = latest->cc.sample - previous->cc.sample;
713 tmp *= (latest->voltage / 10000);
714 val->intval = div64_s64(tmp, 100);
717 accumulator = latest->cc.accumulator - previous->cc.accumulator;
719 latest->cc.offset);
720 tmp *= ((latest->voltage + previous->voltage) / 20000);
721 val->intval = div64_s64(tmp, 100);
725 if (!empty->voltage || !ddata->charge_full)
726 return -ENODATA;
727 /* (ddata->charge_full / 200) is needed for rounding */
728 val->intval = empty->counter_uah - latest->counter_uah +
729 ddata->charge_full / 200;
730 val->intval = clamp(val->intval, 0, ddata->charge_full);
731 val->intval = val->intval * 100 / ddata->charge_full;
735 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
736 else if (latest->voltage >= 3750000)
737 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
738 else if (latest->voltage >= 3300000)
739 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
740 else if (latest->voltage > 3100000)
741 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
742 else if (latest->voltage <= 3100000)
743 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
745 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
749 if (!empty->voltage)
750 return -ENODATA;
751 val->intval = empty->counter_uah - latest->counter_uah;
752 if (val->intval < 0) {
753 /* Assume invalid config if CHARGE_NOW is -20% */
754 if (ddata->charge_full && abs(val->intval) > ddata->charge_full/5) {
755 empty->voltage = 0;
756 ddata->charge_full = 0;
757 return -ENODATA;
759 val->intval = 0;
760 } else if (ddata->charge_full && ddata->charge_full < val->intval) {
762 if (val->intval > (6*ddata->charge_full)/5) {
763 empty->voltage = 0;
764 ddata->charge_full = 0;
765 return -ENODATA;
767 val->intval = ddata->charge_full;
771 if (!ddata->charge_full)
772 return -ENODATA;
773 val->intval = ddata->charge_full;
776 val->intval = ddata->config.info.charge_full_design;
779 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
783 return -ENODATA;
784 val->intval = latest->temperature;
787 return -EINVAL;
803 return -ENODEV;
834 if (val->intval < ddata->config.info.voltage_min_design)
835 return -EINVAL;
836 if (val->intval > ddata->config.info.voltage_max_design)
837 return -EINVAL;
839 ddata->config.bat.constant_charge_voltage_max_uv = val->intval;
841 return cpcap_battery_update_charger(ddata, val->intval);
843 if (val->intval < 0)
844 return -EINVAL;
845 if (val->intval > (6*ddata->config.info.charge_full_design)/5)
846 return -EINVAL;
848 ddata->charge_full = val->intval;
852 return -EINVAL;
876 if (!atomic_read(&ddata->active))
879 list_for_each_entry(d, &ddata->irq_list, node) {
880 if (irq == d->irq)
884 if (list_entry_is_head(d, &ddata->irq_list, node))
889 switch (d->action) {
891 dev_info(ddata->dev, "Coulomb counter calibration done\n");
894 if (latest->current_ua >= 0)
895 dev_warn(ddata->dev, "Battery low at %imV!\n",
896 latest->voltage / 1000);
899 if (latest->current_ua >= 0 && latest->voltage <= 3200000) {
900 dev_emerg(ddata->dev,
902 latest->voltage / 1000);
910 power_supply_changed(ddata->psy);
926 error = devm_request_threaded_irq(ddata->dev, irq, NULL,
931 dev_err(ddata->dev, "could not get irq %s: %i\n",
937 d = devm_kzalloc(ddata->dev, sizeof(*d), GFP_KERNEL);
939 return -ENOMEM;
941 d->name = name;
942 d->irq = irq;
945 d->action = CPCAP_BATTERY_IRQ_ACTION_CC_CAL_DONE;
947 d->action = CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW;
949 d->action = CPCAP_BATTERY_IRQ_ACTION_POWEROFF;
951 list_add(&d->node, &ddata->irq_list);
976 error = regmap_update_bits(ddata->reg, CPCAP_REG_BPEOL,
993 ddata->channels[i] = devm_iio_channel_get(ddata->dev,
995 if (IS_ERR(ddata->channels[i])) {
996 error = PTR_ERR(ddata->channels[i]);
1000 if (!ddata->channels[i]->indio_dev) {
1001 error = -ENXIO;
1009 return dev_err_probe(ddata->dev, error,
1010 "could not initialize VBUS or ID IIO\n");
1019 error = regmap_read(ddata->reg, CPCAP_REG_CCC1, &ccc1);
1026 error = regmap_update_bits(ddata->reg, CPCAP_REG_CCC1,
1033 error = regmap_read(ddata->reg, CPCAP_REG_CCC1, &value);
1040 error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value);
1048 error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value);
1052 dev_info(ddata->dev, "calibration done: 0x%04x\n", value);
1056 dev_err(ddata->dev, "%s: error %i\n", __func__, error);
1058 error = regmap_update_bits(ddata->reg, CPCAP_REG_CCC1,
1061 dev_err(ddata->dev, "%s: restore error %i\n",
1070 .compatible = "motorola,cpcap-battery",
1094 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
1096 return -ENOMEM;
1100 INIT_LIST_HEAD(&ddata->irq_list);
1101 ddata->dev = &pdev->dev;
1103 ddata->reg = dev_get_regmap(ddata->dev->parent, NULL);
1104 if (!ddata->reg)
1105 return -ENODEV;
1107 error = cpcap_get_vendor(ddata->dev, ddata->reg, &ddata->vendor);
1111 switch (ddata->vendor) {
1113 ddata->cc_lsb = 95374; /* μAms per LSB */
1116 ddata->cc_lsb = 91501; /* μAms per LSB */
1119 return -EINVAL;
1121 ddata->cc_lsb = (ddata->cc_lsb * ddata->config.cd_factor) / 1000;
1133 psy_cfg.fwnode = dev_fwnode(&pdev->dev);
1136 ddata->psy = devm_power_supply_register(ddata->dev,
1139 error = PTR_ERR_OR_ZERO(ddata->psy);
1141 dev_err(ddata->dev, "failed to register power supply\n");
1145 atomic_set(&ddata->active, 1);
1159 atomic_set(&ddata->active, 0);
1160 error = regmap_update_bits(ddata->reg, CPCAP_REG_BPEOL,
1163 dev_err(&pdev->dev, "could not disable: %i\n", error);