Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: supply: sc27xx: Optimize the battery capacity calibration

This patch factors out the capacity calibration into one single function
to calibrate the battery capacity, and adding more abnormal cases to
calibrate the capacity when the OCV value is not matchable with current
capacity.

Moreover we also allow to calibrate the capacity when charger magager
tries to get current capacity to make sure we give a correct capacity
for userspace.

Signed-off-by: Yuanjiang Yu <yuanjiang.yu@unisoc.com>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Yuanjiang Yu and committed by
Sebastian Reichel
58066527 ff062d06

+102 -45
+102 -45
drivers/power/supply/sc27xx_fuel_gauge.c
··· 109 109 }; 110 110 111 111 static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity); 112 + static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data, 113 + int cap, bool int_mode); 112 114 113 115 static const char * const sc27xx_charger_supply_name[] = { 114 116 "sc2731_charger", ··· 391 389 delta_cap = DIV_ROUND_CLOSEST(temp * 100, data->total_cap); 392 390 *cap = delta_cap + data->init_cap; 393 391 392 + /* Calibrate the battery capacity in a normal range. */ 393 + sc27xx_fgu_capacity_calibration(data, *cap, false); 394 + 394 395 return 0; 395 396 } 396 397 ··· 666 661 667 662 static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap) 668 663 { 664 + int ret; 665 + 669 666 data->init_cap = cap; 670 - data->init_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, data->init_cap); 667 + ret = sc27xx_fgu_get_clbcnt(data, &data->init_clbcnt); 668 + if (ret) 669 + dev_err(data->dev, "failed to get init coulomb counter\n"); 670 + } 671 + 672 + static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data, 673 + int cap, bool int_mode) 674 + { 675 + int ret, ocv, chg_sts, adc; 676 + 677 + ret = sc27xx_fgu_get_vbat_ocv(data, &ocv); 678 + if (ret) { 679 + dev_err(data->dev, "get battery ocv error.\n"); 680 + return; 681 + } 682 + 683 + ret = sc27xx_fgu_get_status(data, &chg_sts); 684 + if (ret) { 685 + dev_err(data->dev, "get charger status error.\n"); 686 + return; 687 + } 688 + 689 + /* 690 + * If we are in charging mode, then we do not need to calibrate the 691 + * lower capacity. 692 + */ 693 + if (chg_sts == POWER_SUPPLY_STATUS_CHARGING) 694 + return; 695 + 696 + if ((ocv > data->cap_table[0].ocv && cap < 100) || cap > 100) { 697 + /* 698 + * If current OCV value is larger than the max OCV value in 699 + * OCV table, or the current capacity is larger than 100, 700 + * we should force the inititial capacity to 100. 701 + */ 702 + sc27xx_fgu_adjust_cap(data, 100); 703 + } else if (ocv <= data->cap_table[data->table_len - 1].ocv) { 704 + /* 705 + * If current OCV value is leass than the minimum OCV value in 706 + * OCV table, we should force the inititial capacity to 0. 707 + */ 708 + sc27xx_fgu_adjust_cap(data, 0); 709 + } else if ((ocv > data->cap_table[data->table_len - 1].ocv && cap <= 0) || 710 + (ocv > data->min_volt && cap <= data->alarm_cap)) { 711 + /* 712 + * If current OCV value is not matchable with current capacity, 713 + * we should re-calculate current capacity by looking up the 714 + * OCV table. 715 + */ 716 + int cur_cap = power_supply_ocv2cap_simple(data->cap_table, 717 + data->table_len, ocv); 718 + 719 + sc27xx_fgu_adjust_cap(data, cur_cap); 720 + } else if (ocv <= data->min_volt) { 721 + /* 722 + * If current OCV value is less than the low alarm voltage, but 723 + * current capacity is larger than the alarm capacity, we should 724 + * adjust the inititial capacity to alarm capacity. 725 + */ 726 + if (cap > data->alarm_cap) { 727 + sc27xx_fgu_adjust_cap(data, data->alarm_cap); 728 + } else { 729 + int cur_cap; 730 + 731 + /* 732 + * If current capacity is equal with 0 or less than 0 733 + * (some error occurs), we should adjust inititial 734 + * capacity to the capacity corresponding to current OCV 735 + * value. 736 + */ 737 + cur_cap = power_supply_ocv2cap_simple(data->cap_table, 738 + data->table_len, 739 + ocv); 740 + sc27xx_fgu_adjust_cap(data, cur_cap); 741 + } 742 + 743 + if (!int_mode) 744 + return; 745 + 746 + /* 747 + * After adjusting the battery capacity, we should set the 748 + * lowest alarm voltage instead. 749 + */ 750 + data->min_volt = data->cap_table[data->table_len - 1].ocv; 751 + data->alarm_cap = power_supply_ocv2cap_simple(data->cap_table, 752 + data->table_len, 753 + data->min_volt); 754 + 755 + adc = sc27xx_fgu_voltage_to_adc(data, data->min_volt / 1000); 756 + regmap_update_bits(data->regmap, 757 + data->base + SC27XX_FGU_LOW_OVERLOAD, 758 + SC27XX_FGU_LOW_OVERLOAD_MASK, adc); 759 + } 671 760 } 672 761 673 762 static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id) 674 763 { 675 764 struct sc27xx_fgu_data *data = dev_id; 676 - int ret, cap, ocv, adc; 765 + int ret, cap; 677 766 u32 status; 678 767 679 768 mutex_lock(&data->lock); ··· 793 694 if (ret) 794 695 goto out; 795 696 796 - ret = sc27xx_fgu_get_vbat_ocv(data, &ocv); 797 - if (ret) 798 - goto out; 799 - 800 - /* 801 - * If current OCV value is less than the minimum OCV value in OCV table, 802 - * which means now battery capacity is 0%, and we should adjust the 803 - * inititial capacity to 0. 804 - */ 805 - if (ocv <= data->cap_table[data->table_len - 1].ocv) { 806 - sc27xx_fgu_adjust_cap(data, 0); 807 - } else if (ocv <= data->min_volt) { 808 - /* 809 - * If current OCV value is less than the low alarm voltage, but 810 - * current capacity is larger than the alarm capacity, we should 811 - * adjust the inititial capacity to alarm capacity. 812 - */ 813 - if (cap > data->alarm_cap) { 814 - sc27xx_fgu_adjust_cap(data, data->alarm_cap); 815 - } else if (cap <= 0) { 816 - int cur_cap; 817 - 818 - /* 819 - * If current capacity is equal with 0 or less than 0 820 - * (some error occurs), we should adjust inititial 821 - * capacity to the capacity corresponding to current OCV 822 - * value. 823 - */ 824 - cur_cap = power_supply_ocv2cap_simple(data->cap_table, 825 - data->table_len, 826 - ocv); 827 - sc27xx_fgu_adjust_cap(data, cur_cap); 828 - } 829 - 830 - /* 831 - * After adjusting the battery capacity, we should set the 832 - * lowest alarm voltage instead. 833 - */ 834 - data->min_volt = data->cap_table[data->table_len - 1].ocv; 835 - adc = sc27xx_fgu_voltage_to_adc(data, data->min_volt / 1000); 836 - regmap_update_bits(data->regmap, data->base + SC27XX_FGU_LOW_OVERLOAD, 837 - SC27XX_FGU_LOW_OVERLOAD_MASK, adc); 838 - } 697 + sc27xx_fgu_capacity_calibration(data, cap, true); 839 698 840 699 out: 841 700 mutex_unlock(&data->lock);