@@ -109,6 +109,8 @@ struct sc27xx_fgu_data {
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" ,
@@ -389,6 +391,9 @@ static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap)
389
391
delta_cap = DIV_ROUND_CLOSEST (temp * 100 , data -> total_cap );
390
392
* cap = delta_cap + data -> init_cap ;
391
393
394
+ /* Calibrate the battery capacity in a normal range. */
395
+ sc27xx_fgu_capacity_calibration (data , * cap , false);
396
+
392
397
return 0 ;
393
398
}
394
399
@@ -661,50 +666,62 @@ static const struct power_supply_desc sc27xx_fgu_desc = {
661
666
662
667
static void sc27xx_fgu_adjust_cap (struct sc27xx_fgu_data * data , int cap )
663
668
{
669
+ int ret ;
670
+
664
671
data -> init_cap = cap ;
665
- data -> init_clbcnt = sc27xx_fgu_cap_to_clbcnt (data , data -> init_cap );
672
+ ret = sc27xx_fgu_get_clbcnt (data , & data -> init_clbcnt );
673
+ if (ret )
674
+ dev_err (data -> dev , "failed to get init coulomb counter\n" );
666
675
}
667
676
668
- static irqreturn_t sc27xx_fgu_interrupt (int irq , void * dev_id )
677
+ static void sc27xx_fgu_capacity_calibration (struct sc27xx_fgu_data * data ,
678
+ int cap , bool int_mode )
669
679
{
670
- struct sc27xx_fgu_data * data = dev_id ;
671
- int ret , cap , ocv , adc ;
672
- u32 status ;
673
-
674
- mutex_lock (& data -> lock );
680
+ int ret , ocv , chg_sts , adc ;
675
681
676
- ret = regmap_read (data -> regmap , data -> base + SC27XX_FGU_INT_STS ,
677
- & status );
678
- if (ret )
679
- goto out ;
682
+ ret = sc27xx_fgu_get_vbat_ocv (data , & ocv );
683
+ if (ret ) {
684
+ dev_err (data -> dev , "get battery ocv error.\n" );
685
+ return ;
686
+ }
680
687
681
- ret = regmap_update_bits (data -> regmap , data -> base + SC27XX_FGU_INT_CLR ,
682
- status , status );
683
- if (ret )
684
- goto out ;
688
+ ret = sc27xx_fgu_get_status (data , & chg_sts );
689
+ if (ret ) {
690
+ dev_err (data -> dev , "get charger status error.\n" );
691
+ return ;
692
+ }
685
693
686
694
/*
687
- * When low overload voltage interrupt happens, we should calibrate the
688
- * battery capacity in lower voltage stage .
695
+ * If we are in charging mode, then we do not need to calibrate the
696
+ * lower capacity .
689
697
*/
690
- if (!( status & SC27XX_FGU_LOW_OVERLOAD_INT ) )
691
- goto out ;
698
+ if (chg_sts == POWER_SUPPLY_STATUS_CHARGING )
699
+ return ;
692
700
693
- ret = sc27xx_fgu_get_capacity (data , & cap );
694
- if (ret )
695
- goto out ;
696
-
697
- ret = sc27xx_fgu_get_vbat_ocv (data , & ocv );
698
- if (ret )
699
- goto out ;
700
-
701
- /*
702
- * If current OCV value is less than the minimum OCV value in OCV table,
703
- * which means now battery capacity is 0%, and we should adjust the
704
- * inititial capacity to 0.
705
- */
706
- if (ocv <= data -> cap_table [data -> table_len - 1 ].ocv ) {
701
+ if ((ocv > data -> cap_table [0 ].ocv && cap < 100 ) || cap > 100 ) {
702
+ /*
703
+ * If current OCV value is larger than the max OCV value in
704
+ * OCV table, or the current capacity is larger than 100,
705
+ * we should force the inititial capacity to 100.
706
+ */
707
+ sc27xx_fgu_adjust_cap (data , 100 );
708
+ } else if (ocv <= data -> cap_table [data -> table_len - 1 ].ocv ) {
709
+ /*
710
+ * If current OCV value is leass than the minimum OCV value in
711
+ * OCV table, we should force the inititial capacity to 0.
712
+ */
707
713
sc27xx_fgu_adjust_cap (data , 0 );
714
+ } else if ((ocv > data -> cap_table [data -> table_len - 1 ].ocv && cap <= 0 ) ||
715
+ (ocv > data -> min_volt && cap <= data -> alarm_cap )) {
716
+ /*
717
+ * If current OCV value is not matchable with current capacity,
718
+ * we should re-calculate current capacity by looking up the
719
+ * OCV table.
720
+ */
721
+ int cur_cap = power_supply_ocv2cap_simple (data -> cap_table ,
722
+ data -> table_len , ocv );
723
+
724
+ sc27xx_fgu_adjust_cap (data , cur_cap );
708
725
} else if (ocv <= data -> min_volt ) {
709
726
/*
710
727
* If current OCV value is less than the low alarm voltage, but
@@ -713,7 +730,7 @@ static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id)
713
730
*/
714
731
if (cap > data -> alarm_cap ) {
715
732
sc27xx_fgu_adjust_cap (data , data -> alarm_cap );
716
- } else if ( cap <= 0 ) {
733
+ } else {
717
734
int cur_cap ;
718
735
719
736
/*
@@ -728,15 +745,55 @@ static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id)
728
745
sc27xx_fgu_adjust_cap (data , cur_cap );
729
746
}
730
747
748
+ if (!int_mode )
749
+ return ;
750
+
731
751
/*
732
752
* After adjusting the battery capacity, we should set the
733
753
* lowest alarm voltage instead.
734
754
*/
735
755
data -> min_volt = data -> cap_table [data -> table_len - 1 ].ocv ;
756
+ data -> alarm_cap = power_supply_ocv2cap_simple (data -> cap_table ,
757
+ data -> table_len ,
758
+ data -> min_volt );
759
+
736
760
adc = sc27xx_fgu_voltage_to_adc (data , data -> min_volt / 1000 );
737
- regmap_update_bits (data -> regmap , data -> base + SC27XX_FGU_LOW_OVERLOAD ,
761
+ regmap_update_bits (data -> regmap ,
762
+ data -> base + SC27XX_FGU_LOW_OVERLOAD ,
738
763
SC27XX_FGU_LOW_OVERLOAD_MASK , adc );
739
764
}
765
+ }
766
+
767
+ static irqreturn_t sc27xx_fgu_interrupt (int irq , void * dev_id )
768
+ {
769
+ struct sc27xx_fgu_data * data = dev_id ;
770
+ int ret , cap ;
771
+ u32 status ;
772
+
773
+ mutex_lock (& data -> lock );
774
+
775
+ ret = regmap_read (data -> regmap , data -> base + SC27XX_FGU_INT_STS ,
776
+ & status );
777
+ if (ret )
778
+ goto out ;
779
+
780
+ ret = regmap_update_bits (data -> regmap , data -> base + SC27XX_FGU_INT_CLR ,
781
+ status , status );
782
+ if (ret )
783
+ goto out ;
784
+
785
+ /*
786
+ * When low overload voltage interrupt happens, we should calibrate the
787
+ * battery capacity in lower voltage stage.
788
+ */
789
+ if (!(status & SC27XX_FGU_LOW_OVERLOAD_INT ))
790
+ goto out ;
791
+
792
+ ret = sc27xx_fgu_get_capacity (data , & cap );
793
+ if (ret )
794
+ goto out ;
795
+
796
+ sc27xx_fgu_capacity_calibration (data , cap , true);
740
797
741
798
out :
742
799
mutex_unlock (& data -> lock );
0 commit comments