@@ -349,6 +349,11 @@ struct power_supply_resistance_temp_table {
349349 int resistance ; /* internal resistance percent */
350350};
351351
352+ struct power_supply_vbat_ri_table {
353+ int vbat_uv ; /* Battery voltage in microvolt */
354+ int ri_uohm ; /* Internal resistance in microohm */
355+ };
356+
352357/**
353358 * struct power_supply_maintenance_charge_table - setting for maintenace charging
354359 * @charge_current_max_ua: maintenance charging current that is used to keep
@@ -460,7 +465,14 @@ struct power_supply_maintenance_charge_table {
460465 * @factory_internal_resistance_uohm: the internal resistance of the battery
461466 * at fabrication time, expressed in microohms. This resistance will vary
462467 * depending on the lifetime and charge of the battery, so this is just a
463- * nominal ballpark figure.
468+ * nominal ballpark figure. This internal resistance is given for the state
469+ * when the battery is discharging.
470+ * @factory_internal_resistance_charging_uohm: the internal resistance of the
471+ * battery at fabrication time while charging, expressed in microohms.
472+ * The charging process will affect the internal resistance of the battery
473+ * so this value provides a better resistance under these circumstances.
474+ * This resistance will vary depending on the lifetime and charge of the
475+ * battery, so this is just a nominal ballpark figure.
464476 * @ocv_temp: array indicating the open circuit voltage (OCV) capacity
465477 * temperature indices. This is an array of temperatures in degrees Celsius
466478 * indicating which capacity table to use for a certain temperature, since
@@ -498,6 +510,21 @@ struct power_supply_maintenance_charge_table {
498510 * by temperature: highest temperature with lowest resistance first, lowest
499511 * temperature with highest resistance last.
500512 * @resist_table_size: the number of items in the resist_table.
513+ * @vbat2ri_discharging: this is a table that correlates Battery voltage (VBAT)
514+ * to internal resistance (Ri). The resistance is given in microohm for the
515+ * corresponding voltage in microvolts. The internal resistance is used to
516+ * determine the open circuit voltage so that we can determine the capacity
517+ * of the battery. These voltages to resistance tables apply when the battery
518+ * is discharging. The table must be ordered descending by voltage: highest
519+ * voltage first.
520+ * @vbat2ri_discharging_size: the number of items in the vbat2ri_discharging
521+ * table.
522+ * @vbat2ri_charging: same function as vbat2ri_discharging but for the state
523+ * when the battery is charging. Being under charge changes the battery's
524+ * internal resistance characteristics so a separate table is needed.*
525+ * The table must be ordered descending by voltage: highest voltage first.
526+ * @vbat2ri_charging_size: the number of items in the vbat2ri_charging
527+ * table.
501528 * @bti_resistance_ohm: The Battery Type Indicator (BIT) nominal resistance
502529 * in ohms for this battery, if an identification resistor is mounted
503530 * between a third battery terminal and ground. This scheme is used by a lot
@@ -512,7 +539,9 @@ struct power_supply_maintenance_charge_table {
512539 * use these for consistency.
513540 *
514541 * Its field names must correspond to elements in enum power_supply_property.
515- * The default field value is -EINVAL.
542+ * The default field value is -EINVAL or NULL for pointers.
543+ *
544+ * CC/CV CHARGING:
516545 *
517546 * The charging parameters here assume a CC/CV charging scheme. This method
518547 * is most common with Lithium Ion batteries (other methods are possible) and
@@ -597,6 +626,66 @@ struct power_supply_maintenance_charge_table {
597626 * Overcharging Lithium Ion cells can be DANGEROUS and lead to fire or
598627 * explosions.
599628 *
629+ * DETERMINING BATTERY CAPACITY:
630+ *
631+ * Several members of the struct deal with trying to determine the remaining
632+ * capacity in the battery, usually as a percentage of charge. In practice
633+ * many chargers uses a so-called fuel gauge or coloumb counter that measure
634+ * how much charge goes into the battery and how much goes out (+/- leak
635+ * consumption). This does not help if we do not know how much capacity the
636+ * battery has to begin with, such as when it is first used or was taken out
637+ * and charged in a separate charger. Therefore many capacity algorithms use
638+ * the open circuit voltage with a look-up table to determine the rough
639+ * capacity of the battery. The open circuit voltage can be conceptualized
640+ * with an ideal voltage source (V) in series with an internal resistance (Ri)
641+ * like this:
642+ *
643+ * +-------> IBAT >----------------+
644+ * | ^ |
645+ * [ ] Ri | |
646+ * | | VBAT |
647+ * o <---------- | |
648+ * +| ^ | [ ] Rload
649+ * .---. | | |
650+ * | V | | OCV | |
651+ * '---' | | |
652+ * | | | |
653+ * GND +-------------------------------+
654+ *
655+ * If we disconnect the load (here simplified as a fixed resistance Rload)
656+ * and measure VBAT with a infinite impedance voltage meter we will get
657+ * VBAT = OCV and this assumption is sometimes made even under load, assuming
658+ * Rload is insignificant. However this will be of dubious quality because the
659+ * load is rarely that small and Ri is strongly nonlinear depending on
660+ * temperature and how much capacity is left in the battery due to the
661+ * chemistry involved.
662+ *
663+ * In many practical applications we cannot just disconnect the battery from
664+ * the load, so instead we often try to measure the instantaneous IBAT (the
665+ * current out from the battery), estimate the Ri and thus calculate the
666+ * voltage drop over Ri and compensate like this:
667+ *
668+ * OCV = VBAT - (IBAT * Ri)
669+ *
670+ * The tables vbat2ri_discharging and vbat2ri_charging are used to determine
671+ * (by interpolation) the Ri from the VBAT under load. These curves are highly
672+ * nonlinear and may need many datapoints but can be found in datasheets for
673+ * some batteries. This gives the compensated open circuit voltage (OCV) for
674+ * the battery even under load. Using this method will also compensate for
675+ * temperature changes in the environment: this will also make the internal
676+ * resistance change, and it will affect the VBAT under load, so correlating
677+ * VBAT to Ri takes both remaining capacity and temperature into consideration.
678+ *
679+ * Alternatively a manufacturer can specify how the capacity of the battery
680+ * is dependent on the battery temperature which is the main factor affecting
681+ * Ri. As we know all checmical reactions are faster when it is warm and slower
682+ * when it is cold. You can put in 1500mAh and only get 800mAh out before the
683+ * voltage drops too low for example. This effect is also highly nonlinear and
684+ * the purpose of the table resist_table: this will take a temperature and
685+ * tell us how big percentage of Ri the specified temperature correlates to.
686+ * Usually we have 100% of the factory_internal_resistance_uohm at 25 degrees
687+ * Celsius.
688+ *
600689 * The power supply class itself doesn't use this struct as of now.
601690 */
602691
@@ -621,6 +710,7 @@ struct power_supply_battery_info {
621710 int alert_high_temp_charge_current_ua ;
622711 int alert_high_temp_charge_voltage_uv ;
623712 int factory_internal_resistance_uohm ;
713+ int factory_internal_resistance_charging_uohm ;
624714 int ocv_temp [POWER_SUPPLY_OCV_TEMP_MAX ];
625715 int temp_ambient_alert_min ;
626716 int temp_ambient_alert_max ;
@@ -632,6 +722,10 @@ struct power_supply_battery_info {
632722 int ocv_table_size [POWER_SUPPLY_OCV_TEMP_MAX ];
633723 struct power_supply_resistance_temp_table * resist_table ;
634724 int resist_table_size ;
725+ struct power_supply_vbat_ri_table * vbat2ri_discharging ;
726+ int vbat2ri_discharging_size ;
727+ struct power_supply_vbat_ri_table * vbat2ri_charging ;
728+ int vbat2ri_charging_size ;
635729 int bti_resistance_ohm ;
636730 int bti_resistance_tolerance ;
637731};
@@ -675,6 +769,8 @@ extern int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info,
675769extern int
676770power_supply_temp2resist_simple (struct power_supply_resistance_temp_table * table ,
677771 int table_len , int temp );
772+ extern int power_supply_vbat2ri (struct power_supply_battery_info * info ,
773+ int vbat_uv , bool charging );
678774extern struct power_supply_maintenance_charge_table *
679775power_supply_get_maintenance_charging_setting (struct power_supply_battery_info * info , int index );
680776extern bool power_supply_battery_bti_in_range (struct power_supply_battery_info * info ,
@@ -696,6 +792,19 @@ power_supply_supports_maintenance_charging(struct power_supply_battery_info *inf
696792 return (mt != NULL );
697793}
698794
795+ static inline bool
796+ power_supply_supports_vbat2ri (struct power_supply_battery_info * info )
797+ {
798+ return ((info -> vbat2ri_discharging != NULL ) &&
799+ info -> vbat2ri_discharging_size > 0 );
800+ }
801+
802+ static inline bool
803+ power_supply_supports_temp2ri (struct power_supply_battery_info * info )
804+ {
805+ return ((info -> resist_table != NULL ) &&
806+ info -> resist_table_size > 0 );
807+ }
699808
700809#ifdef CONFIG_POWER_SUPPLY
701810extern int power_supply_is_system_supplied (void );
0 commit comments