power: pm8921-bms: adjust rbatt and ocv both for shutdown soc

When ocv (open circuit voltage of the battery) is adjusted to match a
specific soc, rbatt (the battery resistance) changes too. This is because
rbatt is dependent on the remaining charge which changes as the ocv
changes.

The issue we observed with this changing rbatt was the unusable charge
changes which causes the soc to move away from the soc the algorithm
attempts to match.

To get around this issue adjust both the rbatt and ocv when we want to
match a soc for a specific soc.

Change-Id: Ifa8efe1e37b9982d6d67730f911e47e369e9b4ff
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: use background work to calculate soc

The soc (state of charge) calculation algorithms and the associated
adjusting algorithms were coded assuming that the soc will be queried
at distant intervals (more than 20 seconds).

However this assumption is bad and soc can be queried at sub second
intervals. These soc queries in quick succession causes the adjusting
algorithm to over correct the battery voltage.

Separate the soc calculation from the soc reporting - calculate soc
at specific intervals, while the reporting uses the values resulting
from the latest calculation. This way the adjusting algorithms run
at specified intervals and are not perturbed by the sub second querying
for soc.

Change-Id: I240bfdbd3ae3b2e37ae16cc3757a25f5a918e972
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: iterate rbatt algorithm

When ocv (open circuit voltage of the battery) is adjusted to match a
specific soc, rbatt (the battery resistance) changes too. This is
because rbatt is dependent on the remaining charge which changes as
the ocv changes.

The issue we observed with this changing rbatt was the unusable charge
changes which causes the soc to move away from the soc the algorithm
attempts to match.

To get around this issue adjust both the rbatt and ocv in a iterative
fashion until rbatt value stabilizes.

Change-Id: Id3e36c1a8361a6d71b63fca3e6b0c2a4a9bb7e06
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: dont adjust at high battery capacity

The adjusting algorithm was designed to prevent uvlo event towards
low state of charge situations. It works by decreasing ocv so that the
a lower soc is reported.

When the battery is fully charged, we fake an ocv event, causing the
ocv to jump to 100% and cc to 0. But after a few milliseconds when
charging stops, the adjusting algorithm reduces the ocv which
causes the SOC to jump from 100% to 99%.

This jump from 100 to 99 is incorrect. Moreover we have seen quick
decreases at high soc range because of the adjusting algorithm.
To fix that and the 100 to 99% jumps simply don't run the adjusting
algorithm when the battery soc is above 90%.

Change-Id: I68e8bb72ec0e58552f9fedecceaffbf149c1f10e
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: use shutdown soc if it is within limits

When a strong battery is removed, it was seen that the battery voltage
lines on the phone take about five to six seconds to go below 2.1volts
where the pmic resets all the battery backed registers.

If a new battery is plugged in within this time the driver will force
the shutdown soc on this battery which is incorrect.

Compare the shutdown soc with the calculated soc and if they are
different than a configurable limit, simply discard the shutdown soc
and use the calculated soc.

Change-Id: I02e7c78eb5e9df0127ce7e78b0bd9792a8141039
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: change power on ocv if soc < 0

When a phone boots up with a weak battery the ocv (open circuit voltage)
is so low that we end up in  a -ve soc.

If a charger is plugged in, it takes a while for that -ve soc to reach
0. Until then the reported soc is returned 0. (note the driver
never reports a -ve soc). This creates an impression that it takes very
long to go from 0% to 1%.

Change this by bumping up the pon ocv a bit such that soc is reported
exact 0.

Change-Id: I3244723845920c9538dff7e72dab253fd4aa7e2b
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: provide option to ignore shutdown soc

Few platforms do not want to use the shutdown soc. Provide a option to
selectively disable it.

Change-Id: Ie57d474f4e81e4ce2e7e7a4a92cda20d4c8dd184
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: use rtc to get average current

The wall time does keep track of time when the device
is suspended. This causes the average current values to be high.

Use rtc clock instead of the monotonic clock api. Since the rtc
clock has only one second resolution the driver rejects calculating
average current if it is invoked in less than 15 seconds. In such
cases it uses the previously calculated average current.

Change-Id: Ie0a8dc51273606cc3deac69600f22fe05139a4b5
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: backup average current along with shutdown soc

When a phone shuts down because of 0% State of charge (soc) while it is
under heavy load, the unusable charge value is very high. The unusable
charge value is based on load.

When the device restarts, that load has significantly decreased
causing uuc value to reduce. This in turn increases the soc. In certain
cases the increase is so large that it falls beyond the shutdown soc
limit checks and a higher soc value is reported. That is unacceptable.

This problem can be addressed if we can remember the load used to
calculate uuc between restarts.  Use the lower nibble of register 0x105
to store the average current. Since we want finer resolution towards higher
current let the first step be 500mA and then each increment be 50mA steps.

Also since we are saving the range of load between restarts fill up all
the load samples in uuc calculation with this value. This emulates a
low pass filter on current changes and increases/decreases uuc
gradually.

Change-Id: I4f2ab27865756243d023f48798cc002ff12a9d31
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: limit voltage correction

The "adjust_soc" algorithm where we change the open circuit voltage
(ocv) in steps so that the state of charge (soc) starts approaching
the estimated soc, causes nonlinearity in the soc curves if an incorrect
resistance value is fed to the algorithm.

As battery ages and temperature changes, it is hard to estimate the
exact battery resistance.

So to fix the nonlinearity, limit the amount by which the ocv is
changed. Make it proportional to the current, i.e. change ocv by
small amounts in light load and let it change by proportionally
large amounts in heavy load situations.

Also, make the point where the soc is adjusted configurable via platform
data instead of forcing it to 25%.

Change-Id: Idc141e6bf3172dab278afe1900f5a1f9cdd624dd
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: increase/decrease UUC 1% at a time

We see huge jumps in Unusable Charge (UUC) as temperature, average
load or state of charge (SOC) changes, which results in huge jumps
in the reported capacity.

Increase/Decrease UUC slowly (limit 1%) each time SOC is requested.
This results in linearity improvements.

Change-Id: I82022aa499a53c5ea42e7079e96d3c94dfc0be01
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: use termination battery resistance

Unusable Charge(UUC) is based on battery resistance and average load. Since
battery resistance is based on temperature and state of charge, UUC
is essentially based on temperature, state of charge and the load.

The purpose of UUC is to prevent the battery from falling below the
cutoff voltage. In the current implementation, since UUC is dependent
on SOC, it is small when SOC is high and gets bigger as SOC approaches
zero. This increase however is not linear which causes huge jumps in
SOC.

Remove the dependence of UUC on SOC. Simply use the resistance value
which would have been used when SOC = 0.

To find this resistance value, loop from SOC = 0 towards 100 and at each
step calculate/interpolate open circuit voltage, resistance and the
corresponding unusable voltage. The interpolated resistance value where
unusable voltage equals open circuit voltage is the termination
resistance. Use this resistance value for calculation of UUC. Note that
this resistance value is not dependent on the current SOC and will be
constant as long as the load and temperature remain the same.

Change-Id: I3ba91f8b1cb831e257f72363058a6e3a04ffc39b
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-charger: round up vddmax adjustments

It was observed that the battery was charged at voltage less than the
max voltage. This was because the vdd max algorithm rounded down the
voltage.

Use voltage rounding up instead.

Change-Id: Ifb5e9c265b8f616e82abbb979ecfac5e6604b25d
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: charging curve adjustments

It was observed that while charging the reported soc sometimes reaches
100% before end of charging happens. At other times it does not reach
100% at end of charge and a abrupt jump to 100% soc happens.

Fix this by linearly increasing soc based on battery charge current
after constant voltage phase is reached. Constant voltage phase is
reached when battery voltage reaches the max value.

Also once constant voltage phase is reached and the voltage or charge
current decreases keep reporting the earlier soc. This could be because
of a transient system load.

Change-Id: I14c2f42d7897041db038ce85ce1124cf1ef261af
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: change OCV when scaling soc for charging

A drop in state of charge (soc) was observed right after End Of Charge
(EOC) happens. This was because calculated soc was still low, while the
scaling algorithm increased the SOC to 100%. There was a situation
where SOC was calculated right when charging finished but charger did not
send the EOC to bms - the charging adjustments algorithm does not scale
since it sees charging is stopped and falls back to the calculated soc
which was lower than the scaled soc.

Fix this by changing the calculated OCV(open circuit voltage) of the
battery so that the calculated soc is same as the scaled soc.

Change-Id: Ieb409721da6fc70d673ccbf4334f94a1793dfe7e
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: remove forcing shutdown soc

Forcing to return shutdown soc for the first 30 seconds was added so
that we show consistent soc right after bootup.

However with the recent changes to the algorithm viz. using termination
resistance for UUC, restricting UUC changes at most 1% and limiting the
OCV corrections, this forcing is not required. The soc stays within
limits of the shutdown soc.

Remove this forcing of shutdown soc.

Change-Id: Ie74e9318cca29ab60436df6ddec286917fbd0cd7
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-bms: fix 0% soc reported when started with a charger

When the device is started with a charger inserted, it reports 0% soc.
This is because a variable "soc_at_cv" is not initialized correctly in
the probe function.

Fix this by initializing it appropriately to -EINVAL.

Change-Id: I106f36e204c5cc4f16a8f52b9fa7a2a012282e35
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-charger: reject vbus calls after checking vbat

Only reject VBUS requests after also checking the VBAT line
to ensure there is actually not other power source present.

Change-Id: Ie846e1d0450e62cddb69bd64a654214215fe2b2b
Signed-off-by: David Keitel <dkeitel@codeaurora.org>
power: pm8921-bms: fix fake battery emulation

With the recent split of functions to calculate and report state of
charge, the faking battery feature broke, it remained in the calculate
function.

Move the fake battery feature in the reporting function, where it really
belongs.

Change-Id: Ibc2ecdbca32911b4f35c7e6c2278631a614227fa
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
power: pm8921-charger: remove old workarounds

PMIC8921 revision 1.0 and 1.1 are no longer supported by software.

Remove the applicable workarounds from the driver.

Change-Id: I8c99fcbbf2f7229728236ae1059f4c9cb8dbb065
Signed-off-by: David Keitel <dkeitel@codeaurora.org>