Lines Matching +full:data +full:- +full:out

1 // SPDX-License-Identifier: GPL-2.0-only
68 /* OCV -- Open Circuit Voltage */
83 * corresponding resistor value -- Ohm / C degeree.
85 #define TBAT_NEG_25D 127773 /* -25 */
86 #define TBAT_NEG_10D 54564 /* -10 */
151 * register 1 bit[7:0] -- bit[11:4] of measured value of voltage
152 * register 0 bit[3:0] -- bit[3:0] of measured value of voltage
155 int offset, int *data) in measure_12bit_voltage() argument
160 ret = pm860x_bulk_read(info->i2c, offset, 2, buf); in measure_12bit_voltage()
164 *data = ((buf[0] & 0xff) << 4) | (buf[1] & 0x0f); in measure_12bit_voltage()
165 /* V_MEAS(mV) = data * 1.8 * 1000 / (2^12) */ in measure_12bit_voltage()
166 *data = ((*data & 0xfff) * 9 * 25) >> 9; in measure_12bit_voltage()
171 int *data) in measure_vbatt() argument
178 ret = measure_12bit_voltage(info, PM8607_VBAT_MEAS1, data); in measure_vbatt()
182 *data *= 3; in measure_vbatt()
188 * bit[11:10] -- bit[7:6] of LDO9(0x18) in measure_vbatt()
189 * bit[9:8] -- bit[7:6] of LDO8(0x17) in measure_vbatt()
190 * bit[7:6] -- bit[7:6] of LDO7(0x16) in measure_vbatt()
191 * bit[5:4] -- bit[7:6] of LDO6(0x15) in measure_vbatt()
192 * bit[3:0] -- bit[7:4] of LDO5(0x14) in measure_vbatt()
194 ret = pm860x_bulk_read(info->i2c, PM8607_LDO5, 5, buf); in measure_vbatt()
200 /* V_BATT_MEAS(mV) = data * 3 * 1.8 * 1000 / (2^12) */ in measure_vbatt()
201 *data = ((*data & 0xff) * 27 * 25) >> 9; in measure_vbatt()
204 return -EINVAL; in measure_vbatt()
210 * Return value is signed data.
213 static int measure_current(struct pm860x_battery_info *info, int *data) in measure_current() argument
219 ret = pm860x_bulk_read(info->i2c, PM8607_IBAT_MEAS1, 2, buf); in measure_current()
225 *data = s >> 3; in measure_current()
229 static int set_charger_current(struct pm860x_battery_info *info, int data, in set_charger_current() argument
234 if (data < 50 || data > 1600 || !old) in set_charger_current()
235 return -EINVAL; in set_charger_current()
237 data = ((data - 50) / 50) & 0x1f; in set_charger_current()
238 *old = pm860x_reg_read(info->i2c, PM8607_CHG_CTRL2); in set_charger_current()
240 ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL2, 0x1f, data); in set_charger_current()
252 ret = pm860x_set_bits(info->i2c, PM8607_CCNT, 7, offset & 7); in read_ccnt()
254 goto out; in read_ccnt()
255 ret = pm860x_bulk_read(info->i2c, PM8607_CCNT_MEAS1, 2, buf); in read_ccnt()
257 goto out; in read_ccnt()
260 out: in read_ccnt()
268 int data; in calc_ccnt() local
270 ret = read_ccnt(info, CCNT_POS1, &data); in calc_ccnt()
272 goto out; in calc_ccnt()
273 sum = data & 0xffff; in calc_ccnt()
274 ret = read_ccnt(info, CCNT_POS2, &data); in calc_ccnt()
276 goto out; in calc_ccnt()
277 sum |= (data & 0xffff) << 16; in calc_ccnt()
278 ccnt->pos += sum; in calc_ccnt()
280 ret = read_ccnt(info, CCNT_NEG1, &data); in calc_ccnt()
282 goto out; in calc_ccnt()
283 sum = data & 0xffff; in calc_ccnt()
284 ret = read_ccnt(info, CCNT_NEG2, &data); in calc_ccnt()
286 goto out; in calc_ccnt()
287 sum |= (data & 0xffff) << 16; in calc_ccnt()
289 ccnt->neg += sum; in calc_ccnt()
291 ret = read_ccnt(info, CCNT_SPOS, &data); in calc_ccnt()
293 goto out; in calc_ccnt()
294 ccnt->spos += data; in calc_ccnt()
295 ret = read_ccnt(info, CCNT_SNEG, &data); in calc_ccnt()
297 goto out; in calc_ccnt()
300 * charge(mAh) = count * 1.6984 * 1e(-8) in calc_ccnt()
304 ccnt->total_chg = (int) ((ccnt->pos * 18236) >> 40); in calc_ccnt()
305 ccnt->total_dischg = (int) ((ccnt->neg * 18236) >> 40); in calc_ccnt()
307 out: in calc_ccnt()
313 int data; in clear_ccnt() local
317 read_ccnt(info, CCNT_POS1, &data); in clear_ccnt()
318 read_ccnt(info, CCNT_POS2, &data); in clear_ccnt()
319 read_ccnt(info, CCNT_NEG1, &data); in clear_ccnt()
320 read_ccnt(info, CCNT_NEG2, &data); in clear_ccnt()
321 read_ccnt(info, CCNT_SPOS, &data); in clear_ccnt()
322 read_ccnt(info, CCNT_SNEG, &data); in clear_ccnt()
331 int data; in calc_ocv() local
338 return -EINVAL; in calc_ocv()
341 ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); in calc_ocv()
343 goto out; in calc_ocv()
344 vbatt_sum += data; in calc_ocv()
345 ret = measure_current(info, &data); in calc_ocv()
347 goto out; in calc_ocv()
348 ibatt_sum += data; in calc_ocv()
353 mutex_lock(&info->lock); in calc_ocv()
354 if (info->present) in calc_ocv()
355 *ocv = vbatt_avg - ibatt_avg * info->resistor / 1000; in calc_ocv()
358 mutex_unlock(&info->lock); in calc_ocv()
359 dev_dbg(info->dev, "VBAT average:%d, OCV:%d\n", vbatt_avg, *ocv); in calc_ocv()
361 out: in calc_ocv()
371 int ret = -EINVAL; in calc_soc()
374 return -EINVAL; in calc_soc()
388 if (ocv < array_soc[count - 1][0]) { in calc_soc()
402 static irqreturn_t pm860x_coulomb_handler(int irq, void *data) in pm860x_coulomb_handler() argument
404 struct pm860x_battery_info *info = data; in pm860x_coulomb_handler()
410 static irqreturn_t pm860x_batt_handler(int irq, void *data) in pm860x_batt_handler() argument
412 struct pm860x_battery_info *info = data; in pm860x_batt_handler()
415 mutex_lock(&info->lock); in pm860x_batt_handler()
416 ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); in pm860x_batt_handler()
418 info->present = 1; in pm860x_batt_handler()
419 info->temp_type = PM860X_TEMP_TBAT; in pm860x_batt_handler()
421 info->present = 0; in pm860x_batt_handler()
422 info->temp_type = PM860X_TEMP_TINT; in pm860x_batt_handler()
424 mutex_unlock(&info->lock); in pm860x_batt_handler()
434 int data; in pm860x_init_battery() local
439 data = MEAS1_GP1; in pm860x_init_battery()
440 if (info->temp_type == PM860X_TEMP_TINT) in pm860x_init_battery()
441 data |= MEAS1_TINT; in pm860x_init_battery()
442 ret = pm860x_set_bits(info->i2c, PM8607_MEAS_EN1, data, data); in pm860x_init_battery()
444 goto out; in pm860x_init_battery()
447 data = MEAS3_IBAT | MEAS3_BAT_DET | MEAS3_CC; in pm860x_init_battery()
448 ret = pm860x_set_bits(info->i2c, PM8607_MEAS_EN3, data, data); in pm860x_init_battery()
450 goto out; in pm860x_init_battery()
453 ret = pm860x_reg_write(info->i2c, PM8607_MEAS_OFF_TIME1, 0x82); in pm860x_init_battery()
455 goto out; in pm860x_init_battery()
456 ret = pm860x_reg_write(info->i2c, PM8607_MEAS_OFF_TIME2, 0x6c); in pm860x_init_battery()
458 goto out; in pm860x_init_battery()
461 ret = pm860x_set_bits(info->i2c, PM8607_GPADC_MISC1, in pm860x_init_battery()
464 goto out; in pm860x_init_battery()
467 ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL6, in pm860x_init_battery()
470 goto out; in pm860x_init_battery()
472 ret = pm860x_set_bits(info->i2c, PM8607_CCNT, 7 << 3, in pm860x_init_battery()
475 goto out; in pm860x_init_battery()
478 ret = pm860x_set_bits(info->i2c, PM8607_GP_BIAS2, 0xF << 4, in pm860x_init_battery()
481 goto out; in pm860x_init_battery()
484 mutex_lock(&info->lock); in pm860x_init_battery()
485 ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); in pm860x_init_battery()
487 mutex_unlock(&info->lock); in pm860x_init_battery()
488 goto out; in pm860x_init_battery()
491 info->present = 1; in pm860x_init_battery()
492 info->temp_type = PM860X_TEMP_TBAT; in pm860x_init_battery()
494 info->present = 0; in pm860x_init_battery()
495 info->temp_type = PM860X_TEMP_TINT; in pm860x_init_battery()
497 mutex_unlock(&info->lock); in pm860x_init_battery()
501 goto out; in pm860x_init_battery()
503 data = pm860x_reg_read(info->i2c, PM8607_POWER_UP_LOG); in pm860x_init_battery()
504 bat_remove = data & BAT_WU_LOG; in pm860x_init_battery()
506 dev_dbg(info->dev, "battery wake up? %s\n", in pm860x_init_battery()
511 buf[0] = pm860x_reg_read(info->i2c, PM8607_RTC_MISC2); in pm860x_init_battery()
512 buf[1] = pm860x_reg_read(info->i2c, PM8607_RTC1); in pm860x_init_battery()
513 data = ((buf[1] & 0x3) << 5) | ((buf[0] >> 3) & 0x1F); in pm860x_init_battery()
514 if (data > soc + 15) in pm860x_init_battery()
515 info->start_soc = soc; in pm860x_init_battery()
516 else if (data < soc - 15) in pm860x_init_battery()
517 info->start_soc = soc; in pm860x_init_battery()
519 info->start_soc = data; in pm860x_init_battery()
520 dev_dbg(info->dev, "soc_rtc %d, soc_ocv :%d\n", data, soc); in pm860x_init_battery()
522 pm860x_set_bits(info->i2c, PM8607_POWER_UP_LOG, in pm860x_init_battery()
524 info->start_soc = soc; in pm860x_init_battery()
526 info->last_capacity = info->start_soc; in pm860x_init_battery()
527 dev_dbg(info->dev, "init soc : %d\n", info->last_capacity); in pm860x_init_battery()
528 out: in pm860x_init_battery()
535 int data; in set_temp_threshold() local
539 data = 0; in set_temp_threshold()
541 data = (min << 8) / 1800; in set_temp_threshold()
542 pm860x_reg_write(info->i2c, PM8607_GPADC1_HIGHTH, data); in set_temp_threshold()
543 dev_dbg(info->dev, "TEMP_HIGHTH : min: %d, 0x%x\n", min, data); in set_temp_threshold()
546 data = 0xff; in set_temp_threshold()
548 data = (max << 8) / 1800; in set_temp_threshold()
549 pm860x_reg_write(info->i2c, PM8607_GPADC1_LOWTH, data); in set_temp_threshold()
550 dev_dbg(info->dev, "TEMP_LOWTH:max : %d, 0x%x\n", max, data); in set_temp_threshold()
553 static int measure_temp(struct pm860x_battery_info *info, int *data) in measure_temp() argument
560 if (info->temp_type == PM860X_TEMP_TINT) { in measure_temp()
561 ret = measure_12bit_voltage(info, PM8607_TINT_MEAS1, data); in measure_temp()
564 *data = (*data - 884) * 1000 / 3611; in measure_temp()
566 ret = measure_12bit_voltage(info, PM8607_GPADC1_MEAS1, data); in measure_temp()
570 *data = (*data * 1000) / GPBIAS2_GPADC1_UA; in measure_temp()
572 if (*data > TBAT_NEG_25D) { in measure_temp()
573 temp = -30; /* over cold , suppose -30 roughly */ in measure_temp()
576 } else if (*data > TBAT_NEG_10D) { in measure_temp()
577 temp = -15; /* -15 degree, code */ in measure_temp()
580 } else if (*data > TBAT_0D) { in measure_temp()
581 temp = -5; /* -5 degree */ in measure_temp()
585 } else if (*data > TBAT_10D) { in measure_temp()
590 } else if (*data > TBAT_20D) { in measure_temp()
595 } else if (*data > TBAT_30D) { in measure_temp()
600 } else if (*data > TBAT_40D) { in measure_temp()
611 dev_dbg(info->dev, "temp_C:%d C,temp_mv:%d mv\n", temp, *data); in measure_temp()
612 *data = temp; in measure_temp()
624 int data; in calc_resistor() local
628 ret = measure_current(info, &data); in calc_resistor()
629 /* make sure that charging is launched by data > 0 */ in calc_resistor()
630 if (ret || data < 0) in calc_resistor()
631 goto out; in calc_resistor()
633 ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); in calc_resistor()
635 goto out; in calc_resistor()
637 if (data < VBATT_RESISTOR_MIN || data > VBATT_RESISTOR_MAX) in calc_resistor()
638 goto out; in calc_resistor()
642 goto out; in calc_resistor()
651 ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); in calc_resistor()
654 vbatt_sum1 += data; in calc_resistor()
655 ret = measure_current(info, &data); in calc_resistor()
659 if (data < 0) in calc_resistor()
660 ibatt_sum1 = ibatt_sum1 - data; /* discharging */ in calc_resistor()
662 ibatt_sum1 = ibatt_sum1 + data; /* charging */ in calc_resistor()
674 ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); in calc_resistor()
677 vbatt_sum2 += data; in calc_resistor()
678 ret = measure_current(info, &data); in calc_resistor()
682 if (data < 0) in calc_resistor()
683 ibatt_sum2 = ibatt_sum2 - data; /* discharging */ in calc_resistor()
685 ibatt_sum2 = ibatt_sum2 + data; /* charging */ in calc_resistor()
695 data = 1000 * (vbatt_sum1 - vbatt_sum2) in calc_resistor()
696 / (ibatt_sum1 - ibatt_sum2); in calc_resistor()
697 if ((data - info->resistor > 0) && in calc_resistor()
698 (data - info->resistor < info->resistor)) in calc_resistor()
699 info->resistor = data; in calc_resistor()
700 if ((info->resistor - data > 0) && in calc_resistor()
701 (info->resistor - data < data)) in calc_resistor()
702 info->resistor = data; in calc_resistor()
708 out: in calc_resistor()
709 return -EINVAL; in calc_resistor()
715 int data; in calc_capacity() local
722 goto out; in calc_capacity()
724 data = info->max_capacity * info->start_soc / 100; in calc_capacity()
725 if (ccnt_data.total_dischg - ccnt_data.total_chg <= data) { in calc_capacity()
727 data + ccnt_data.total_chg - ccnt_data.total_dischg; in calc_capacity()
730 calc_soc(info, OCV_MODE_ACTIVE, &info->start_soc); in calc_capacity()
731 dev_dbg(info->dev, "restart soc = %d !\n", in calc_capacity()
732 info->start_soc); in calc_capacity()
736 cap_cc = cap_cc * 100 / info->max_capacity; in calc_capacity()
742 dev_dbg(info->dev, "%s, last cap : %d", __func__, in calc_capacity()
743 info->last_capacity); in calc_capacity()
747 goto out; in calc_capacity()
752 cap_ocv = info->last_capacity; in calc_capacity()
753 ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); in calc_capacity()
755 goto out; in calc_capacity()
756 if (data <= LOW_BAT_THRESHOLD) { in calc_capacity()
768 if (cap_cc < 15 && cap_ocv - cap_cc > 10) in calc_capacity()
775 if (*cap > info->last_capacity) in calc_capacity()
776 *cap = info->last_capacity; in calc_capacity()
780 info->last_capacity = *cap; in calc_capacity()
782 dev_dbg(info->dev, "%s, cap_ocv:%d cap_cc:%d, cap:%d\n", in calc_capacity()
789 pm860x_set_bits(info->i2c, PM8607_RTC_MISC2, RTC_SOC_5LSB, in calc_capacity()
791 pm860x_set_bits(info->i2c, PM8607_RTC1, RTC_SOC_3MSB, in calc_capacity()
794 out: in calc_capacity()
800 struct pm860x_battery_info *info = dev_get_drvdata(psy->dev.parent); in pm860x_external_power_changed()
809 struct pm860x_battery_info *info = dev_get_drvdata(psy->dev.parent); in pm860x_batt_get_prop()
810 int data; in pm860x_batt_get_prop() local
815 val->intval = info->present; in pm860x_batt_get_prop()
818 ret = calc_capacity(info, &data); in pm860x_batt_get_prop()
821 if (data < 0) in pm860x_batt_get_prop()
822 data = 0; in pm860x_batt_get_prop()
823 else if (data > 100) in pm860x_batt_get_prop()
824 data = 100; in pm860x_batt_get_prop()
826 if (!info->present) in pm860x_batt_get_prop()
827 data = 100; in pm860x_batt_get_prop()
828 val->intval = data; in pm860x_batt_get_prop()
831 val->intval = POWER_SUPPLY_TECHNOLOGY_LION; in pm860x_batt_get_prop()
835 ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); in pm860x_batt_get_prop()
838 val->intval = data * 1000; in pm860x_batt_get_prop()
842 ret = calc_ocv(info, &data); in pm860x_batt_get_prop()
845 val->intval = data * 1000; in pm860x_batt_get_prop()
848 ret = measure_current(info, &data); in pm860x_batt_get_prop()
851 val->intval = data; in pm860x_batt_get_prop()
854 if (info->present) { in pm860x_batt_get_prop()
855 ret = measure_temp(info, &data); in pm860x_batt_get_prop()
858 data *= 10; in pm860x_batt_get_prop()
861 data = 250; in pm860x_batt_get_prop()
863 val->intval = data; in pm860x_batt_get_prop()
866 return -ENODEV; in pm860x_batt_get_prop()
875 struct pm860x_battery_info *info = dev_get_drvdata(psy->dev.parent); in pm860x_batt_set_prop()
880 info->start_soc = 100; in pm860x_batt_set_prop()
881 dev_dbg(info->dev, "chg done, update soc = %d\n", in pm860x_batt_set_prop()
882 info->start_soc); in pm860x_batt_set_prop()
885 return -EPERM; in pm860x_batt_set_prop()
903 .name = "battery-monitor",
914 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); in pm860x_battery_probe()
919 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); in pm860x_battery_probe()
921 return -ENOMEM; in pm860x_battery_probe()
923 info->irq_cc = platform_get_irq(pdev, 0); in pm860x_battery_probe()
924 if (info->irq_cc <= 0) in pm860x_battery_probe()
925 return -EINVAL; in pm860x_battery_probe()
927 info->irq_batt = platform_get_irq(pdev, 1); in pm860x_battery_probe()
928 if (info->irq_batt <= 0) in pm860x_battery_probe()
929 return -EINVAL; in pm860x_battery_probe()
931 info->chip = chip; in pm860x_battery_probe()
932 info->i2c = in pm860x_battery_probe()
933 (chip->id == CHIP_PM8607) ? chip->client : chip->companion; in pm860x_battery_probe()
934 info->dev = &pdev->dev; in pm860x_battery_probe()
935 info->status = POWER_SUPPLY_STATUS_UNKNOWN; in pm860x_battery_probe()
936 pdata = pdev->dev.platform_data; in pm860x_battery_probe()
938 mutex_init(&info->lock); in pm860x_battery_probe()
943 if (pdata && pdata->max_capacity) in pm860x_battery_probe()
944 info->max_capacity = pdata->max_capacity; in pm860x_battery_probe()
946 info->max_capacity = 1500; /* set default capacity */ in pm860x_battery_probe()
947 if (pdata && pdata->resistor) in pm860x_battery_probe()
948 info->resistor = pdata->resistor; in pm860x_battery_probe()
950 info->resistor = 300; /* set default internal resistor */ in pm860x_battery_probe()
952 info->battery = devm_power_supply_register(&pdev->dev, in pm860x_battery_probe()
955 if (IS_ERR(info->battery)) in pm860x_battery_probe()
956 return PTR_ERR(info->battery); in pm860x_battery_probe()
957 info->battery->dev.parent = &pdev->dev; in pm860x_battery_probe()
959 ret = devm_request_threaded_irq(chip->dev, info->irq_cc, NULL, in pm860x_battery_probe()
963 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", in pm860x_battery_probe()
964 info->irq_cc, ret); in pm860x_battery_probe()
968 ret = devm_request_threaded_irq(chip->dev, info->irq_batt, NULL, in pm860x_battery_probe()
972 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", in pm860x_battery_probe()
973 info->irq_batt, ret); in pm860x_battery_probe()
985 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); in pm860x_battery_suspend()
988 chip->wakeup_flag |= 1 << PM8607_IRQ_CC; in pm860x_battery_suspend()
995 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); in pm860x_battery_resume()
998 chip->wakeup_flag &= ~(1 << PM8607_IRQ_CC); in pm860x_battery_resume()
1008 .name = "88pm860x-battery",