Motorola Mobility. MMI Charger Specific Bindings

As a common charger driver mmi_charger inherits Motorola legacy battery
charging features, including Demo charging, Step charging, Flash Fast
charging, and common features for factory test support.

More importantly, it provides a cross-platform solution to support
various battery charging design, not only Qualcomm SoC but also Samsung,
MTK, even remote system over network, and especially suite multiple
battery packs and multiple charger ICs in one system.

To achieve this goal, besides mmi_charger driver, there need a low level
charger driver for each battery charging solution(a couple of charger IC
& battery pack) to register to mmi_charger driver with implementation of
required interfaces depending on their own HW design.

With mmi_charger driver, Motorola common features have been stripped
from the HW dependent charger drivers(older Motorola charger drivers),
in which all the common features have to be implemented by each driver
of its own. So a low level charger driver can focus on HW specific
features and function development.

Motorola charger driver architecture:
-----------------------------------------------------------------------------------------------------------
Userspace  Common Interfaces for Charging Features and Factory Test
-----------------------------------------------------------------------------------------------------------
Kernel           mmi_charger (Motorola demo, step, flash-fast charging,
                /     |      \ factory and debugging interfaces)
               /      |       \
    qti_glink_charger x_charger N_charger (basic charging functions HW
              |       |        | specific factory debugging interfaces)
              |       |        |
------------glink----i2c------spmi--------------------------------------------------------------------------
              |       |        |
              |       |        |
            ADSP   i2c chip   PMIC

Benefit from this new Motorola charger driver design:
1. Easy upgrade, migration, and maintenance, as common driver is
   cross-platform and HW independent.
2. Reduce develop workload, as developers can pay more energy and
   efforts on HW or platform specific business logic.
3. Easy to support complex battery charging solution, as it can support
   N couples of charger IC & battery pack in one system at the same time
   theoretically.

Motorola common charger driver is built as DLKM:
Module Name: mmi_charger.ko
Log Tag: mmi_charger
IPC Log: /d/ipc_logging/mmi_charger/log
Support Platform: platform independent

Motorola platform charger driver is built as DLKM:
(1) qti_glink_charger
Module Name: qti_glink_charger.ko
Log Tag: qti_glink_charger
IPC Log: /d/ipc_logging/mmi_charger/log
Support Platform: SM8350/SM7325(adsp and HLOS connection over glink)
(2) qpnp_smb_basic_charger
Module Name: qpnp_smb_basic_charger.ko
Log Tag: pmxxx_charger
IPC Log: /d/ipc_logging/mmi_charger/log
Support Platform: SM6125/SM710/SM636/SM7250/SM6350(qpnp smb charger with multi-battery support)

devicetree properties description:
mmi_charger:
- mmi,enable-charging-limit
 Usage:      optional
 Value Type: <empty>
 Definition: Boolean flag to set capacity limits to battery when plugged on
a charger and is executing a Factory Image. It will use upper and lower
capacities defined by the Device Tree.

- mmi,enable-factory-poweroff
 Usage:      optional
 Value Type: <empty>
 Definition: Boolean flag which enables Factory Kill when executing under a
Factory Image. By default, Factory Kill is a feature only in Factory Mode,
which turns the device off when charger is removed.

- mmi,upper-limit-capacity
 Usage:      optional
 Value Type: <u32>
 Definition: Limits minimum battery SoC (in percentage). In other words, starts
charging when it reaches this value. Especially useful for factory procedures,
which needs to limit SoC. Requires qcom,enable-charging-limit. If not defined,
defaults to 100.

- mmi,lower-limit-capacity
 Usage:      optional
 Value Type: <u32>
 Definition: Limits maximum battery SoC (in percentage). In other words, stop
charging when it reaches this value. Especially useful for factory procedures,
which needs to limit SoC. Requires qcom,enable-charging-limit. If not defined,
defaults to 0.

- mmi,dcp-power-max
 Usage:      optional
 Value Type: <u32>
 Definition: Set this value to allow power in mW draw from DC charger, used
 when a normal DCP charger is detected. If not set, 7.5W power is allowed.

- mmi,hvdcp-power-max
 Usage:      optional
 Value Type: <u32>
 Definition: Set this value to allow power in mW draw from QC3.0 charger, used
 when a QC3.0 charger is detected. If not set, 15W power is allowed.

- mmi,pd-power-max
 Usage:      optional
 Value Type: <u32>
 Definition: Set this value to allow power in mW draw from pd charger, used
 when a pd charger is detected. If not set, 15W power is allowed.

- mmi,wls-power-max
 Usage:      optional
 Value Type: <u32>
 Definition: Set this value to allow power in mW draw from wireless charger, used
 when a wireless charger is detected. If not set, 5W power is allowed.

- mmi,heartbeat-interval
Usage:      optional
Value Type: <u32>
Definition: Set the heartbeat interval of in ms, 60s by default if not set.

Example:
mmi_charger: mmi,charger {
	compatible = "mmi,mmi-charger";
	mmi,enable-charging-limit;
	mmi,enable-factory-poweroff;
	mmi,upper-limit-capacity = <75>;
	mmi,lower-limit-capacity = <60>;
	mmi,heartbeat-interval = <60000>;
	mmi,dcp-power-max = <10000>;
	mmi,hvdcp-power-max = <200000>;
	mmi,pd-power-max = <200000>;
	mmi,wls-power-max = <100000>;
};

platform low level charger:
- mmi,mmi-temp-zones
 Usage:      optional
 Value Type: Array of tuples of <u32>
 Definition: Unlimited array of arrays. Each internal array needs to have a set
of 4 bytes, each one representing this sequence: Temperature (in degC), Step
"Normalized" Voltage (in millivolts), Full Rate "FCC" Current (in milliamps),
and Taper Rate "FCC Normalized" Current (in milliamps). These values are
related to charging limitations based on temperature specifications. Note that
setting a voltage to '0' means that it doesn't matter the battery voltage on
that defined temperature range to perform necessary tapering. To understand how
Those values are used, please check the "IEEE Charging Compliance" section below.
In order to support charging current limit based on battery voltage in the same
temperature zone, one zone allows to have multiple lines with ascending sequence
by float voltage. First find the temperature zone, and then find the right one
among the same zone according to current battery voltage.

- mmi,df-serialnum
 Usage:      optional
 Value Type: <string>
 Definition: The default battery serial number for charging profile selection
and battery identification.

- mmi,chrg-iterm-ma
 Usage:      optional
 Value Type: <u32>
 Definition: It will define taper current on battery (in milliamps). If charging
current becomes below this value, it indicates FULL charging. If not defined,
defaults to 300.

- mmi,fg-iterm-ma
 Usage:      optional
 Value Type: <u32>
 Definition: It will define charging current on battery (in milliamps) as the
threshold for the fuel gauge to decide reporting FULL capacity. If not defined,
defaults to 350.

- mmi,vfloat-comp-uv
 Usage:      optional
 Value Type: <u32>
 Definition: This is a tolerance, in uV, for battery floating voltage when
charging is being limited. Such situation can happen when either battery is
close to full or when there's thermal mitigation on charging. If not set,
defaults to 0.

- mmi,max-fv-mv
 Usage:      optional
 Value Type: <u32>
 Definition: It will define the maximum battery charging voltage (in milliamps).
This value is used as the max float voltage for battery charging. If not
defined, defaults to 4400.

- mmi,max-fcc-ma
 Usage:      optional
 Value Type: <u32>
 Definition: It will define maximum charging current on battery (in milliamps)
If not defined, defaults to 4000.

- mmi,demo-fv-mv
 Usage:      optional
 Value Type: <u32>
 Definition: It will define the maximum battery charging voltage (in milliamps)
in demo mode. This value is used as the max float voltage for battery charging in
demo mode. If not defined, defaults to 4000.

- profile-ids-map
 Usage:      optional(qti_glink_charger specific)
 Value Type: Array of <string>
 Definition: Unlimited array of arrays. Each internal array needs to have a set
of 2 data members, each one representing this sequence: Battery Profile ID
(in integer value), Battery Serial Number(provided by battery spec). Battery
profile ID will be set to 0 if this property is not specified.

- mmi,mmi-ffc-zones
 Usage:      optional
 Value Type: Array of tuples of <u32>
 Definition: Unlimited array of arrays. Each internal array needs to have a set
of 4 data members, each one representing this sequence: Temperature (in degC),
maximum Float Voltage (in millivolts), charging terminated current(in milliamps),
and Fuel Gauge FULL terminated current (in milliamps). These values are
related to charging limitations based on temperature specifications when the
battery supports Flash Fast Charging.

- mmi,profile-data-block-size
 Usage:      optional(qti_glink_charger specific)
 Value Type: <u32>
 Definition: It will define the profile data member count each block line
in the profile data array. If not defined, defaults to 4.

- mmi,profile-data
 Usage:      optional(qti_glink_charger specific)
 Value Type: Array of tuples of <u32>
 Definition: Unlimited array of arrays. Each internal array needs to have a set
with member count specified by property "mmi,profile-data-block-size". The content
for each line is defined by the target user of the profile data.

- battery-names
 Usage:      optional(pm7250b_mmi specific)
 Value Type: Array of <string>
 Definition: Unlimited array of arrays. Each internal array specifics a power supply
 name which is used by the driver to get the battery information.

- supplied-from
 Usage:      optional(pm7250b_mmi specific)
 Value Type: Array of <string>
 Definition: Unlimited array of arrays. Each internal array specifics a power supply
 name, the change of which the battery is sensitive to.

- mmi,paired-id
 Usage:      optional
 Value Type: <u32>
 Definition: It will define the paired id for dual battery matching, high-16bits is used
for reference battery paired id, low-16bits is used for target battery paired id,
Only when the target battery paired id is equal to reference battery, then reference battery
information will be notified to the target battery when it is updated.
If not defined, defaults to 0.

Example:
qti_glink_charger: mmi,qti-glink-charger {
	compatible = "mmi,qti-glink-charger";
	mmi,df-serialnum = "unknown-sn";
	mmi,chrg-iterm-ma = <300>;
	mmi,fg-iterm-ma = <350>;
	mmi,max-fv-mv = <4400>;
	mmi,max-fcc-ma = <4000>;
	mmi,demo-fv-mv = <4000>;
	mmi,vfloat-comp-uv = <20000>;
	mmi,mmi-temp-zones =
			<0 4200 880 0>,
			<10 4200 2185 880>,
			<15 0 2185 2185>,
			<45 4000 3600 3600>,
			<45 4250 3600 3000>,
			<45 4350 3000 2000>,
			<60 4200 2185 0>;
	mmi,mmi-ffc-zones =
			<0 4450 243 500>,
			<23 4480 670 980>,
			<35 4480 770 1045>,
			<45 4480 840 1120>,
			<60 4450 243 500>;

	mmi,profile-data-block-size = <4>;
	mmi,profile-data =
			<0 4200 880 0>,
			<10 4200 2185 880>,
			<15 0 2185 2185>,
			<45 4000 3600 3600>,
			<45 4250 3600 3000>,
			<45 4350 3000 2000>,
			<60 4200 2185 0>;
	profile-ids-map = "0", "unknown-sn", "100750", "SB18C85232";
	mmi,paired-id = <0x00010000>;
};

Single-battery Pack:
pm7250b_mmi: qcom,qpnp-smb5-mmi {
	status = "ok";
	compatible = "mmi,qpnp-smb-basic-charger";
	mmi,pmic-revid = <&pm7250b_revid>;
	mmi,usbpd-phandle = <&pm7250b_pdphy>;
	battery-names = "battery";
	supplied-from = "qcom_battery", "mmi_battery";

	mmi,chrg-iterm-ma = <243>;
	mmi,vfloat-comp-uv = <20000>;
	mmi,fg-iterm-ma = <400>;
	mmi,max-fv-mv = <4450>;
	mmi,max-fcc-ma = <4000>;
	mmi,demo-fv-mv = <4000>;
	mmi,df-serialnum = "SB18C85232";
	mmi,mmi-temp-zones = <0 4200 1000 0>,
			<10 4200 2500 1000>,
			<15 0 2500 2500>,
			<45 4200 4000 4000>,
			<60 4200 3600 0>;
};

Multi-battery Pack:
pm7250b_mmi: qcom,qpnp-smb5-mmi {
	status = "ok";
	compatible = "mmi,qpnp-smb-basic-charger";
	mmi,pmic-revid = <&pm7250b_revid>;
	mmi,usbpd-phandle = <&pm7250b_pdphy>;
	battery-names = "fg_main_battery", "fg_flip_battery";
	supplied-from = "qcom_battery", "mmi_battery", "fg_main_battery", "fg_flip_battery";
};

&main_battery {
	mmi,chrg-iterm-ma = <50>;
	mmi,vfloat-comp-uv = <20000>;
	mmi,fg-iterm-ma = <100>;
	mmi,max-fv-mv = <4450>;
	mmi,max-fcc-ma = <4000>;
	mmi,demo-fv-mv = <4000>;
	mmi,df-serialnum = "main_battery-sn";
	mmi,mmi-temp-zones = <0 4200 243 0>,
			<10 4200 608 243>,
			<15 0 608 608>,
			<45 4450 1210 1200>,
			<60 4200 608 0>;
	mmi,paired-id = <0x00010000>;
};

&flip_battery {
	mmi,chrg-iterm-ma = <50>;
	mmi,vfloat-comp-uv = <20000>;
	mmi,fg-iterm-ma = <100>;
	mmi,max-fv-mv = <4450>;
	mmi,max-fcc-ma = <4000>;
	mmi,demo-fv-mv = <4000>;
	mmi,df-serialnum = "flip_battery-sn";
	mmi,mmi-temp-zones = <0 4200 300 0>,
			<10 4200 750 300>,
			<15 0 750 750>,
			<45 4450 1250 1200>,
			<60 4200 750 0>;
	mmi,paired-id = <0x00000001>;
};

==========================
 IEEE Charging Compliance
==========================

In order to be compliant to IEEE rules, there are a series of limitations on
how much a battery can be charged, based on temperature. That will limit how
much current can be drawn, or maximum battery voltage to be achieved during
charging.

Current is always tapered when voltage achieves maximum voltage specification
(which is generally 4.4V, but may have a different value, depending a product
battery specs). It is tapered to some small value, possibly around 100mA,
which is based on product specifications and capacity testing, defined by
EE (Electrical Engineering) Team/Hardware.

If temperature is below -20 degC or above 60 degC, it should automatically
stop charging the device.

If temperature is in between 15 and 45 deg C, it can achieve maximum charging
current, and such value varies across products. Generally, if it supports PD,
this will be a much higher current than non-PD products, which will also have
a much higher current than dual-battery products. Important to note that this
is a rule-of-thumb, so always check product specifications.

If temperature is between 0 and 10 deg C, but battery voltage is above 4.20V,
current should be tapered to 1000mA.

Finally, if temperature is in between -20 and 0 deg C, current should be
tapered to 1000mA.

NOTE1: whenever dealing with IEEE certification, most documentation and
variable notation across the bootloader and kernel may refer to JEITA. This is a
convention on such standards and values to which temperature, voltage and
current levels are accepted in different scenarios for Li-ion batteries. So
JEITA can be seen as a general standard, but IEEE enforces it as well as
provide ways to certify a product according to it (is mandatory to certify
any commercial product that has a lithium-ion battery embedded or plugged to
it).

NOTE2: taper current mostly refers to when battery is above maximum allowed
voltage on a specific temperature region, based on rules above. So be aware
that the rest of this document may refer as "taper" to a current that is
limiting the maximum value, but before achieving a stage in which current
is limited to something around 100mA (so an intermediate stage). Also
"taper voltage" will refer to a voltage level in which this mentioned
"taper" current (intermediate current level) is triggered.


=========================================
 How to define mmi,mmi-temp-zones array
=========================================

When defining qcom,mmi-temp-zones array, it is important to always have in
mind the IEEE rules described above, as well the battery specifications.

Each tuple in that array represents a different value, as shown here:
<temperature taper_volt max_cur_below_taper_volt max_cur_above_taper_volt>

"temperature" defines maximum temperature value. So setting "35" means a
definition to anything below 35 degC.

"taper_volt" means maximum allowed battery voltage in that temperature
range. So setting "4200" means that tapering will happen once battery
is above 4.2V and is still charging.

"max_cur_below_taper_volt" defines maximum allowed current value in case
the battery is below "taper_volt" value. So setting it to "700" means that
current won't go above 700mA, as long as battery is below "taper_volt"
voltage.

"max_cur_above_taper_volt" defines maximum allowed current value in case
battery is above "taper_volt" value. So setting it to "0" means that it
won't charge in case the battery is above "taper_volt" voltage.

Here's an example from Dubai:
		mmi,mmi-temp-zones =
                                        <0 4200 880 0>,
                                        <10 4200 2185 880>,
                                        <15 0 2185 2185>,
                                        <45 4000 3600 3600>,
                                        <45 4250 3600 3000>,
                                        <45 4350 3000 2000>,
                                        <60 4200 2185 0>;
The first line states "If temperature is below 0 degC, and the battery voltage
is below 4.2V, device can be charged up to 880mA. But if the battery voltage
is above 4.2V, device cannot be charged".

The third line states "If temperature is below 15 degC, the battery can be charged
up to 2185mA, no matter the battery voltage".

The fourth to sixth line states that there are three lines in the same zone with
different taper_volt by ascending sequence, the charging current is limited by
both temperature and battery voltage.

=================================================
 Understanding the IEEE algorithm implementation
=================================================

Now that IEEE rules were understood, as well as how qcom,mmi-temp-zones is set,
just to stress out this driver implementation, the thermal charging limitation
implementation will be described.

mmi_basic_charge_sm() or mmi_dual_charge_sm() are the functions responsible
to enforce such rules. In that way, before we check the implementation, here
are some conventions:

STEP_NONE:  no charger present
STEP_STOP:  in zone hot or zone cold, which limits charging considerably
STEP_NORM:  limits current to some value
STEP_MAX:   allows maximum current value, when in between 0 and 45 degC
STEP_FULL:  battery is almost or completely full, tapering to a small current
STEP_FLOAT: TODO

Important to note that even when moving from one state to another, temperature
may change. Hence, taper current and voltage will no longer correspond to such
state, and so is always necessary to check on every state in which temperature
range device is.

"batt_ma" refers to battery current (equivalent to current_now on battery
sysfs).
"taper_ma" is "fcc_norm_ma" in case is in STATE_MAX, which means battery is
above taper voltage. If in any other state, it will refer to "chrg_iterm",
which will depend on device specifications (4.4V batteries have 97mA as
current standards, and 4.45V batteries have 121mA as taper current).

Now, let's check the algorithms for a bit:

-----------------------------------------------------
current-step: STEP_NONE | STEP_STOP
	if norm_mv AND (batt_mv + 50 >= norm_mv) // (1)
		if fcc_norm_ma			 // (2)
			-goto STEP_NORM		 // (2)
		else
			-goto STEP_STOP		 // (2)
	else
		-goto STEP_MAX			 // (1)

(1) are we in a range which has "norm_mv" defined, and battery is above this
value?
This corresponds to most temperature ranges, except in between 15 and 45 degC.
If that's the case, allow charging up to maximum current defined in product
spec.

(2) is "fcc_norm_ma" a value different from zero?
This happens if temperature is in range between 0 and 45 degC. Due to previous
consideration, it is only missing range 0 to 15 degC here. If that's the case,
limit maximum current. Otherwise, battery is above "norm_mv" (which probably
is defined as 4.2V), and at that voltage and temperature, limiting charging
considerably.

-----------------------------------------------------
current-step: STEP_MAX
	if !norm_mv				// (1)
		taper_cnt = 0
		if (batt_mv + 50) > max_fv_mv	// (2)
			-goto STEP_NORM
		else
			-goto STEP_MAX
	else if (batt_mv + 50) < norm_mv	// (1)
		taper_cnt = 0
		-goto STEP_MAX
	else if !fcc_norm_ma			// (3)
		-goto STEP_FLOAT
	else if current_has_tapered		// (4)
		taper_cnt = 0
		if charge_halted
			vote chg_dis_votable
		-goto STEP_NORM

(1) are we in a range which has "norm_mv" NOT defined, or below taper voltage?
This is only for the 15 to 45 degC region, which has no current tapering.

(2) are we above taper voltage?
This checks whether taper voltage was achieved, making current to taper to
defined values, depending on which temperature region battery is at this
moment.

(3) at current temperature, is taper current defined?
If there is a taper current value to current temperature region (which is
usually in between 0 and 15 degC as defined in current implementation), allow
TODO STEP_FLOAT

(4) has current been limited due to other thermal rules?
Function mmi_has_current_tapered() requests to power supply votable module
what is the allowed maximum current. Then such value will be compared to taper
current value, and the minimum will be chosen. Additionally, it checks whether
there's still a charger plugged to device or if charging is disabled, and if
any, mark a flag on the system displaying no charging is going on. Finally, move
to taper the current state (STEP_NORM).

-----------------------------------------------------
current-step: STEP_NORM
	if !fcc_norm_ma						// (1)
		-goto STEP_FLOAT
	else if batt_soc < 100 or (batt_mv + 50) < max_fv_mv	// (2)
		taper_cnt = 0
		-goto STEP_NORM
	else if current_has_tapered				// (2)
		-goto STEP_FULL

(1) although device is in STEP_NORM, is there a defined taper current for
current temperature region device?
It may happen that temperature has changed, and device no longer needs to
be tapered. Hence, move to STEP_FLOAT.

(2) is the battery NOT full or below taper voltage?
Stay in this state, because tapering is still happening. Otherwise, it may
be the case that battery is above taper voltage, or device is already fully
charged, forcing it to prepare to stop charging (STEP_FULL).

-----------------------------------------------------
current-step: STEP_FULL
	if batt_soc < 99		// (1)
		taper_cnt = 0
		goto STEP_NORM

(1) Is the battery no longer full?
It may happen that the battery device was previously full, but no longer is. So,
first move to a limited current state for safety, and then in such state, it
may happen that maximum current levels can be achieved.

-----------------------------------------------------
current-step: STEP_FLOAT
	if fcc_norm_ma or (batt_mv + 50) < norm_mv	// (1)
		goto STEP_MAX
	if current_has_tapered				// (2)
		goto STEP_STOP

(1) does battery temperature allow current to be tapered to something above
0mA, or battery is below taper voltage?
This means that temperature is in between 0 and 15 degC. If so, try to achieve
maximum current value (STEP_MAX).

(2) does current need to be tapered?
In case mmi_has_current_tapered() needs to decrease current, it will request
charger to stop charging.

-----------------------------------------------------
Setting current values based on state machine:

STEP_FLOAT
STEP_MAX
	target_fcc = fcc_max_ma
	target_fv:
		if !norm_mv
			target_fv = max_fv_mv + chip->vfloat_comp_mv
		else
			target_fv = norm_mv + chip->vfloat_comp_mv

STEP_FULL:
	target_fcc = -EINVAL
	target_fv = max_fv_mv

STEP_NORM:
	target_fcc = fcc_norm_ma
	target_fv = max_fv_mv + chip->vfloat_comp_mv

STEP_NONE:
	target_fv = max_fv_mv
	target_fcc = fcc_norm_ma

=========================================
 How to define mmi,mmi-ffc-zones array
=========================================

When defining mmi,mmi-ffc-zones array, it is important to always have in
mind the rules described in the battery specifications, only the battery
support Flash Fast Charging can use it, otherwise battery damage or over
voltage protection may happen.

Each tuple in that array represents a different value, as shown here:
<temperature max_fv_volt charging_term_cur fg_term_cur>

"temperature" defines maximum temperature value. So setting "35" means a
definition to anything below 35 degC.

"max_fv_volt" means maximum allowed battery voltage in that temperature
range. So setting "4480" means that the maximum float voltage is limited
to 4480.

"charging_term_cur" means charging terminated current threshold in that
temperature range. Once the charging current becomes below the threshold,
the charging will be terminated.

"fg_term_cur" means charging current threshold for FG to report full
charged in that temperature range. Once the charging current becomes
below the threshold, the FG will report FULL state of charge.

Here's an example from Dubai:
		mmi,mmi-ffc-zones =
                                        <0 4450 243 500>,
                                        <23 4480 670 980>,
                                        <35 4480 770 1045>,
                                        <45 4480 840 1120>,
                                        <60 4450 243 500>;

The third line states "If temperature is below 35 degC, and the maximum float voltage
is 4.48V, charging terminated current sets to 770mA, Fuel Gauge terminated current
sets to 1045mA.


