CP: add qc3p charge policy

qc3p and  charge pump
add qc3p charge policy

Change-Id: I3af6c3214a88b5ad327f10df1f6afa639d7bfc5b
Reviewed-on: https://gerrit.mot.com/1967489
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
chailu1 2021-06-02 16:46:46 +08:00 • committed by Lu Chai
commit a358f8bae4
12 changed files with 1497 additions and 10 deletions

View file

@ -9,6 +9,8 @@ mmi_parallel_charger_iio-objs += mmi_charger_core.o
mmi_parallel_charger_iio-objs += mmi_charger_pump_policy.o
mmi_parallel_charger_iio-objs += sc8549_charger.o
mmi_parallel_charger_iio-objs += qpnp_pmic_charger.o
mmi_parallel_charger_iio-objs += mmi_qc3p.o
mmi_parallel_charger_iio-objs += mmi_qc3p_cp_policy.o
#ifeq ($(CONFIG_MMI_PL_CP_POLICY), y)
#endif

View file

@ -69,6 +69,14 @@ int mmi_set_charing_current(struct mmi_charger_device *chrg, u32 uA)
return -ENOTSUPP;
}
int mmi_get_vbus(struct mmi_charger_device *chrg, u32 *mv)
{
if(chrg != NULL && chrg->ops != NULL && chrg->ops->get_vbus)
return chrg->ops->get_vbus(chrg,mv);
return -ENOTSUPP;
}
int mmi_get_input_current_settled(struct mmi_charger_device *chrg, u32 *uA)
{
if(chrg != NULL && chrg->ops != NULL && chrg->ops->get_input_current_settled)

View file

@ -97,6 +97,7 @@ struct mmi_charger_ops {
int (*get_charging_current)(struct mmi_charger_device *chrg, u32 *uA);
int (*set_charging_current)(struct mmi_charger_device *chrg, u32 uA);
int (*get_input_current_settled)(struct mmi_charger_device *chrg, u32 *uA);
int (*get_vbus)(struct mmi_charger_device *chrg, u32 *mv);
int (*get_input_current)(struct mmi_charger_device *chrg, u32 *uA);
int (*set_input_current)(struct mmi_charger_device *chrg, u32 uA);
int (*update_charger_status)(struct mmi_charger_device *chrg);
@ -122,6 +123,7 @@ extern int mmi_set_input_current(struct mmi_charger_device *chrg, u32 uA);
extern int mmi_update_charger_status(struct mmi_charger_device *chrg);
extern int mmi_update_charger_error(struct mmi_charger_device *chrg);
extern int mmi_clear_charger_error(struct mmi_charger_device *chrg);
extern int mmi_get_vbus(struct mmi_charger_device *chrg, u32 *mv);
extern struct mmi_charger_ops sc8549_charger_ops;
extern struct mmi_charger_ops qpnp_pmic_charger_ops;
extern struct mmi_charger_device *mmi_charger_device_register(const char *name,

View file

@ -45,6 +45,7 @@
#include "mmi_charger_core.h"
#include "mmi_charger_core_iio.h"
#include "mmi_charger_policy.h"
#include "mmi_qc3p.h"
#include <linux/iio/consumer.h>
#include <linux/qti_power_supply.h>
@ -132,6 +133,7 @@ static int mmi_charger_init_iio_psy(struct mmi_charger_manager *chip,
return rc;
}
static int qc3p_volt_max_init = 0;
static int pd_volt_max_init = 0;
static int pd_curr_max_init = 0;
static int *dt_temp_zones;
@ -1107,8 +1109,33 @@ void clear_chrg_dev_error_cnt(struct mmi_charger_manager *chip, struct mmi_cp_po
return;
}
static void kick_qc3p_sm(struct mmi_charger_manager *chip, int ms)
{
if (!chip->qc3p_sm_work_running) {
mmi_chrg_dbg(chip, PR_INTERRUPT,
"launch mmi qc3p chrg sm work\n");
mmi_qc3p_chrg_policy_clear(chip); //todo
schedule_delayed_work(&chip->mmi_qc3p_chrg_sm_work, //
msecs_to_jiffies(ms)); //todo
chip->qc3p_sm_work_running = true;
} else
mmi_chrg_dbg(chip, PR_INTERRUPT,
"mmi chrg qc3p sm work already existed\n");
}
static void cancel_qc3p_sm(struct mmi_charger_manager *chip)
{
cancel_delayed_work_sync(&chip->mmi_qc3p_chrg_sm_work);
flush_delayed_work(&chip->mmi_qc3p_chrg_sm_work);
mmi_qc3p_chrg_policy_clear(chip);
chip->qc3p_sm_work_running = false;
chip->qc3p_volt_max = qc3p_volt_max_init;
mmi_chrg_dbg(chip, PR_INTERRUPT,
"cancel sync and flush mmi chrg qc3p sm work\n");
}
static void mmi_awake_vote(struct mmi_charger_manager *chip, bool awake)
{
if (awake == chip->awake)
@ -1327,12 +1354,18 @@ static void mmi_heartbeat_work(struct work_struct *work)
break;
}
}
}
if (!chip->qc3p_sm_work_running && chip->vbus_present)
chip->qc3p_active = mmi_qc3p_power_active(chip);
if (chip->pd_pps_support
&& !chip->factory_mode) {
mmi_chrg_info(chip, "MMI: Heartbeat!, launch sm work\n");
kick_sm(chip, 100);
}
if (chip->pd_pps_support
&& !chip->factory_mode) {
mmi_chrg_info(chip, "MMI: Heartbeat!, launch sm work\n");
kick_sm(chip, 100);
} else if(chip->qc3p_active
&& !chip->factory_mode) {
mmi_chrg_info(chip, "MMI: Heartbeat!, launch qc3p sm work\n");
kick_qc3p_sm(chip, 100);
}
if (chip->use_batt_age)
@ -1455,19 +1488,29 @@ static void psy_changed_work_func(struct work_struct *work)
chip->pd_pps_support,
chip->pd_volt_max,
chip->pd_curr_max);
if (chip->vbus_present)
chip->qc3p_active = mmi_qc3p_power_active(chip);
if (chip->vbus_present
&& chip->pd_pps_support
&& !chip->factory_mode) {
kick_sm(chip, 100);
} else if (chip->vbus_present
&& chip->qc3p_active
&& !chip->factory_mode) {
kick_qc3p_sm(chip, 100);
} else {
cancel_sm(chip);
cancel_qc3p_sm(chip);
chip->pd_pps_support = false;
chip->qc3p_active = false;
}
return;
}
#define DEFAULT_IBUS_MAX_MA 3000
#define DEFAULT_QC3P_VOLT_STEPS 20000
#define DEFAULT_QC3P_VOLT_MAX 11000000
#define DEFAULT_BATT_OVP_LMT 4475000
#define DEFAULT_PL_CHRG_VBATT_MIN 3600000
#define DEFAULT_PPS_VOLT_STEPS 20000
@ -1567,6 +1610,27 @@ static int mmi_chrg_manager_parse_dt(struct mmi_charger_manager *chip)
DEFAULT_PPS_CURR_MAX;
pd_curr_max_init = chip->pd_curr_max;
rc = of_property_read_u32(node,
"mmi,qc3p-max-ibus-ma",
&chip->qc3p_max_ibus_ma);
if (rc < 0)
chip->qc3p_max_ibus_ma =
DEFAULT_IBUS_MAX_MA;
rc = of_property_read_u32(node,
"mmi,qc3p-volt-steps",
&chip->qc3p_volt_steps);
if (rc < 0)
chip->qc3p_volt_steps =
DEFAULT_QC3P_VOLT_STEPS;
rc = of_property_read_u32(node,
"mmi,qc3p-volt-max",
&chip->qc3p_volt_max);
if (rc < 0)
chip->qc3p_volt_max =
DEFAULT_QC3P_VOLT_MAX;
qc3p_volt_max_init = chip->qc3p_volt_max;
for_each_child_of_node(node, child)
chip->mmi_chrg_dev_num++;
@ -1864,6 +1928,8 @@ int mmi_chrg_policy_init(struct mmi_charger_manager *chip,
chrg_dev_init(chip, &g_chrg_list);
chip->pps_volt_comp = PPS_INIT_VOLT_COMP;
INIT_DELAYED_WORK(&chip->mmi_chrg_sm_work, mmi_chrg_sm_work_func);
chip->qc3p_volt_comp = QC3P_INIT_VOLT_COMP;
INIT_DELAYED_WORK(&chip->mmi_qc3p_chrg_sm_work, mmi_qc3p_chrg_sm_work_func);
return 0;
}

View file

@ -280,9 +280,32 @@ struct mmi_charger_manager {
int mmi_chrg_dev_num;
struct mmi_charger_device **chrg_list; /*charger device list*/
/*qc3p*/
int qc3p_max_ibus_ma;
int qc3p_power;
bool qc3p_active;
bool qc3p_sm_work_running;
struct delayed_work mmi_qc3p_chrg_sm_work;
int qc3p_request_volt;
int qc3p_request_volt_prev;
int qc3p_target_volt;
int qc3p_batt_therm_volt;
int qc3p_sys_therm_volt;
bool qc3p_recovery_pmic_chrg;
bool qc3p_sys_therm_cooling;
bool qc3p_sys_therm_force_pmic_chrg;
bool qc3p_batt_therm_cooling;
int qc3p_batt_therm_cooling_cnt;
int qc3p_volt_comp;
int qc3p_ibus_max_volt;
int qc3p_volt_steps;
int qc3p_volt_max;
};
#define PPS_INIT_VOLT_COMP 500000
#define QC3P_INIT_VOLT_COMP 500000
extern void mmi_qc3p_chrg_sm_work_func(struct work_struct *work);
extern struct mmi_cp_policy_dev g_chrg_list;
extern const struct mmi_chrg_dev_ops dev_ops[];
extern void clear_chrg_dev_error_cnt(struct mmi_charger_manager *chip, struct mmi_cp_policy_dev *chrg_list);

View file

@ -16,6 +16,10 @@ enum mmi_charger_ext_iio_channels {
SMB5_TYPEC_MODE,
SMB5_USB_INPUT_CURRENT_SETTLED,
SMB5_USB_PD_ACTIVE,
/*qc3p*/
SMB5_USB_REAL_TYPE,
SMB5_DP_DM,
SMB5_QC3P_POWER,
/*sc8549*/
SC8549_CP_ENABLE,
SC8549_INPUT_CURRENT_NOW,
@ -31,6 +35,10 @@ static const char * const mmi_charger_ext_iio_chan_name[] = {
[SMB5_TYPEC_MODE] = "usb_typec_mode",
[SMB5_USB_INPUT_CURRENT_SETTLED] = "usb_input_current_settled",
[SMB5_USB_PD_ACTIVE] = "usb_pd_active",
/*qc3p*/
[SMB5_USB_REAL_TYPE] = "usb_real_type",
[SMB5_DP_DM] = "battery_dp_dm",
[SMB5_QC3P_POWER] = "usb_qc3p_power",
/*sc8549*/
[SC8549_CP_ENABLE] = "sc8549_cp_enable",
[SC8549_INPUT_CURRENT_NOW] = "sc8549_input_current_now",

View file

@ -29,4 +29,5 @@
#define __MMI_CHRG_POLICY_H_
extern void mmi_chrg_policy_clear(struct mmi_charger_manager *chip);
extern void mmi_chrg_enable_all_cp(struct mmi_charger_manager *chip, int val);
extern void mmi_qc3p_chrg_policy_clear(struct mmi_charger_manager *chip);
#endif

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2012 Motorola Mobility, LLC.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mmi_charger_core.h"
#include "mmi_charger_core_iio.h"
#include <linux/qti_power_supply.h>
bool mmi_qc3p_power_active(struct mmi_charger_manager *chg)
{
int ret, iio_val;
ret = mmi_charger_read_iio_chan(chg, SMB5_USB_REAL_TYPE, &iio_val);
if (ret < 0) {
mmi_chrg_err(chg, "Couldn't read charger type rc=%d\n", ret);
return false;
}
if (iio_val != QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3P5)
return false;
ret = mmi_charger_read_iio_chan(chg, SMB5_QC3P_POWER, &iio_val);
if (ret < 0) {
mmi_chrg_err(chg, "Couldn't read qc3p power rc=%d\n", ret);
return false;
}
chg->qc3p_power = iio_val;
mmi_chrg_info(chg, "qc3p_power =%d\n", chg->qc3p_power);
if (chg->qc3p_power == QTI_POWER_SUPPLY_QC3P_27W ||
chg->qc3p_power == QTI_POWER_SUPPLY_QC3P_45W)
return true;
else
return false;
}
#define QC3P_PULSE_COUNT_MAX ((11000 - 5000) / 20 + 10)
int mmi_qc3p_set_vbus_voltage(struct mmi_charger_manager *chg, int target_mv)
{
int rc = -EINVAL;
union power_supply_propval val = {0, };
int pulse_cnt, curr_vbus_mv, step, i;
rc = mmi_charger_read_iio_chan(chg, SMB5_DP_DM, &val.intval);
if (rc < 0) {
mmi_chrg_err(chg, "Couldn't read dpdm pulse count rc=%d\n", rc);
return -EINVAL;
} else {
mmi_chrg_info(chg, "DP DM pulse count = %d\n", val.intval);
pulse_cnt = val.intval;
}
rc = mmi_get_vbus(chg->chrg_list[CP_MASTER],
&curr_vbus_mv);
if (rc) {
mmi_chrg_err(chg, "Unable to read USB voltage: %d\n", rc);
return -EINVAL;
}
if(target_mv < curr_vbus_mv) {
step = (curr_vbus_mv - target_mv) / 20;
val.intval = QTI_POWER_SUPPLY_DP_DM_DM_PULSE;
if (pulse_cnt <= step)
step = pulse_cnt;
} else {
step = (target_mv - curr_vbus_mv) / 20;
val.intval = QTI_POWER_SUPPLY_DP_DM_DP_PULSE;
if (step + pulse_cnt > QC3P_PULSE_COUNT_MAX)
step = QC3P_PULSE_COUNT_MAX - pulse_cnt;
}
mmi_chrg_info(chg, "curr_vbus= %d, target_vbus = %d, step = %d\n",curr_vbus_mv, target_mv, step);
for (i = 0; i < step; i++) {
rc = mmi_charger_write_iio_chan(chg, SMB5_DP_DM, val.intval);
if (rc < 0) {
mmi_chrg_err(chg, "Couldn't set dpdm pulse rc=%d\n", rc);
break;
}
if (i < step - 1)
udelay(5000);
}
rc = mmi_get_vbus(chg->chrg_list[CP_MASTER],
&curr_vbus_mv);
if (rc) {
mmi_chrg_err(chg, "Unable to read VBUS: %d\n", rc);
return -EINVAL;
}
mmi_chrg_info(chg, "result_vbus= %d\n",curr_vbus_mv);
return curr_vbus_mv;
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2021 Motorola Mobility, LLC.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
extern bool mmi_qc3p_power_active(struct mmi_charger_manager *chg);
extern int mmi_qc3p_set_vbus_voltage(struct mmi_charger_manager *chg, int target_mv);

File diff suppressed because it is too large Load diff

View file

@ -87,7 +87,26 @@ static int qpnp_pmic_get_charging_current(struct mmi_charger_device *chrg, u32 *
rc = power_supply_get_property(chrg->chrg_psy,
POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
if (!rc)
*uA = !!prop.intval;
*uA = prop.intval;
return rc;
}
static int qpnp_pmic_get_ibus(struct mmi_charger_device *chrg, u32 *uA)
{
int rc;
static struct power_supply *usb_psy;
union power_supply_propval prop = {0,};
if (!usb_psy)
usb_psy = power_supply_get_by_name("usb");
if (!usb_psy)
return -ENODEV;
rc = power_supply_get_property(usb_psy,
POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
if (!rc)
*uA = prop.intval;
return rc;
}
@ -130,16 +149,22 @@ static int qpnp_pmic_update_charger_status(struct mmi_charger_device *chrg)
{
int rc;
bool value = 0;
struct power_supply *usb_psy;
static struct power_supply *usb_psy = NULL;
union power_supply_propval prop = {0,};
if (!chrg->chrg_psy)
return -ENODEV;
if (!usb_psy)
usb_psy = power_supply_get_by_name("usb");
if (!usb_psy)
return -ENODEV;
rc = power_supply_get_property(usb_psy,
POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
if (!rc)
chrg->charger_data.ibus_curr= prop.intval;
rc = power_supply_get_property(chrg->chrg_psy,
POWER_SUPPLY_PROP_VOLTAGE_NOW, &prop);
if (!rc)
@ -190,6 +215,7 @@ struct mmi_charger_ops qpnp_pmic_charger_ops = {
.enable = qpnp_pmic_enable_charging,
.is_enabled = qpnp_pmic_is_charging_enabled,
.get_charging_current = qpnp_pmic_get_charging_current,
.get_input_current = qpnp_pmic_get_ibus,
.set_charging_current = qpnp_pmic_set_charging_current,
.get_input_current_settled = qpnp_pmic_get_input_current_settled,
.update_charger_status = qpnp_pmic_update_charger_status,

View file

@ -93,7 +93,21 @@ static int sc8549_get_charging_current(struct mmi_charger_device *chrg, u32 *uA)
return rc;
}
static int sc8549_get_input_current(struct mmi_charger_device *chrg, u32 *uA)
static int sc8549_get_vbus(struct mmi_charger_device *chrg, u32 *mv)
{
int rc, val;
struct mmi_charger_manager *chip = dev_get_drvdata(&chrg->dev);
if (!chip)
return -ENODEV;
rc = mmi_charger_read_iio_chan(chip, SC8549_INPUT_VOLTAGE_NOW, &val);
if (!rc)
*mv = val;
return rc;
}
static int sc8549_get_input_current(struct mmi_charger_device *chrg, u32 *uA) //ibus
{
int rc;
int value;
@ -119,6 +133,11 @@ static int sc8549_update_charger_status(struct mmi_charger_device *chrg)
if (!chrg->chrg_psy)
return -ENODEV;
rc = power_supply_get_property(chrg->chrg_psy,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &prop);
if (!rc)
chrg->charger_data.ibus_curr= prop.intval;
rc = power_supply_get_property(chrg->chrg_psy,
POWER_SUPPLY_PROP_VOLTAGE_NOW, &prop);
if (!rc)
@ -197,6 +216,7 @@ struct mmi_charger_ops sc8549_charger_ops = {
.enable = sc8549_enable_charging,
.is_enabled = sc8549_is_charging_enabled,
.get_charging_current = sc8549_get_charging_current,
.get_vbus = sc8549_get_vbus,
.get_input_current = sc8549_get_input_current,
.update_charger_status = sc8549_update_charger_status,
.update_charger_error = sc8549_update_charger_error_status,