power: supply: qcom: Add support to make SMB5 charger GKI compliant

SMB5 charger drivers and their helper files use several power supply
properties on msm-4.19 which cannot be supported on msm-5.4 due to the
need for GKI compliance. Add support for main charger to register
as an IIO device with individual channels under it corresponding to
missing power supply properties from msm-4.19.

Change-Id: I7182160258fa2ebd4af36b0531b11d988cffdbd3
Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
This commit is contained in:
Jishnu Prakash 2020-07-29 20:53:29 +05:30
commit da167e08a9
12 changed files with 2310 additions and 1739 deletions

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig QCOM_POWER_SUPPLY
tristate "Support for Qualcomm Technologies, Inc. power supply"
bool "Support for Qualcomm Technologies, Inc. power supply"
depends on ARCH_QCOM
if QCOM_POWER_SUPPLY
@ -17,17 +17,20 @@ config QPNP_QG
config QPNP_SMB5
tristate "SMB5 Battery Charger"
depends on MFD_SPMI_PMIC
depends on MFD_SPMI_PMIC && IIO
help
Say Y to enables support for the SMB5 charging peripheral.
The QPNP SMB5 charger driver supports the charger peripheral
present in the chip.
The power supply framework is used to communicate battery and
usb properties to userspace and other driver consumers such
The power supply and iio frameworks are used to communicate battery
and usb properties to userspace and other driver consumers such
as fuel gauge, USB, and USB-PD.
VBUS and VCONN regulators are registered for supporting OTG,
and powered Type-C cables respectively.
To compile this driver as a module, choose M here: the
module will be called qpnp-smb5-main.
config SMB1398_CHARGER
tristate "SMB1398 power supply framework based driver"
depends on MFD_I2C_PMIC

View file

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_QPNP_SMB5) += qpnp-smb5-main.o
qpnp-smb5-main-y += step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o battery-profile-loader.o smb5-iio.o
obj-$(CONFIG_QPNP_QG) += qpnp-qg.o battery-profile-loader.o pmic-voter.o qg-util.o qg-soc.o qg-sdam.o qg-battery-profile.o qg-profile-lib.o fg-alg.o
obj-$(CONFIG_QPNP_SMB5) += step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o
obj-$(CONFIG_SMB1398_CHARGER) += smb1398-charger.o pmic-voter.o
obj-$(CONFIG_SMB1355_SLAVE_CHARGER) += smb1355-charger.o pmic-voter.o

File diff suppressed because it is too large Load diff

View file

@ -12,8 +12,10 @@ struct charger_param {
u32 hvdcp2_max_icl_ua;
u32 hvdcp3_max_icl_ua;
u32 forced_main_fcc;
int (*iio_read)(struct device *dev, int iio_chan, int *val);
int (*iio_write)(struct device *dev, int iio_chan, int val);
};
int qcom_batt_init(struct charger_param *param);
int qcom_batt_init(struct device *dev, struct charger_param *param);
void qcom_batt_deinit(void);
#endif /* __BATTERY_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,521 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
#include <linux/pmic-voter.h>
#include <linux/power_supply.h>
#include <linux/iio/consumer.h>
#include "smb5-lib.h"
#include "smb5-iio.h"
#include "smb5-reg.h"
#include "schgm-flash.h"
#define MIN_THERMAL_VOTE_UA 500000
int smb5_iio_get_prop(struct smb_charger *chg, int channel, int *val)
{
union power_supply_propval pval = {0, };
int rc = 0;
u8 reg = 0, buff[2] = {0};
pval.intval = 0;
*val = 0;
switch (channel) {
/* USB */
case PSY_IIO_VOLTAGE_MAX_LIMIT:
if (chg->usbin_forced_max_uv)
*val = chg->usbin_forced_max_uv;
else
rc = smblib_get_prop_usb_voltage_max_design(chg, &pval);
*val = pval.intval;
break;
case PSY_IIO_PD_CURRENT_MAX:
*val = get_client_vote(chg->usb_icl_votable, PD_VOTER);
break;
case PSY_IIO_USB_REAL_TYPE:
*val = chg->real_charger_type;
break;
case PSY_IIO_TYPEC_MODE:
rc = smblib_get_usb_prop_typec_mode(chg, val);
break;
case PSY_IIO_TYPEC_POWER_ROLE:
rc = smblib_get_prop_typec_power_role(chg, val);
break;
case PSY_IIO_TYPEC_CC_ORIENTATION:
rc = smblib_get_prop_typec_cc_orientation(chg, val);
break;
case PSY_IIO_TYPEC_SRC_RP:
rc = smblib_get_prop_typec_select_rp(chg, val);
break;
case PSY_IIO_PD_ACTIVE:
*val = chg->pd_active;
break;
case PSY_IIO_USB_INPUT_CURRENT_SETTLED:
rc = smblib_get_prop_input_current_settled(chg, &pval);
if (!rc)
*val = pval.intval;
break;
case PSY_IIO_PD_IN_HARD_RESET:
rc = smblib_get_prop_pd_in_hard_reset(chg, val);
break;
case PSY_IIO_PD_USB_SUSPEND_SUPPORTED:
*val = chg->system_suspend_supported;
break;
case PSY_IIO_PE_START:
rc = smblib_get_pe_start(chg, val);
break;
case PSY_IIO_CTM_CURRENT_MAX:
*val = get_client_vote(chg->usb_icl_votable, CTM_VOTER);
break;
case PSY_IIO_HW_CURRENT_MAX:
rc = smblib_get_charge_current(chg, val);
break;
case PSY_IIO_PR_SWAP:
rc = smblib_get_prop_pr_swap_in_progress(chg, val);
break;
case PSY_IIO_PD_VOLTAGE_MAX:
*val = chg->voltage_max_uv;
break;
case PSY_IIO_PD_VOLTAGE_MIN:
*val = chg->voltage_min_uv;
break;
case PSY_IIO_CONNECTOR_TYPE:
*val = chg->connector_type;
break;
case PSY_IIO_CONNECTOR_HEALTH:
*val = smblib_get_prop_connector_health(chg);
break;
case PSY_IIO_SMB_EN_MODE:
mutex_lock(&chg->smb_lock);
*val = chg->sec_chg_selected;
mutex_unlock(&chg->smb_lock);
break;
case PSY_IIO_SMB_EN_REASON:
*val = chg->cp_reason;
break;
case PSY_IIO_MOISTURE_DETECTED:
*val = chg->moisture_present;
break;
case PSY_IIO_HVDCP_OPTI_ALLOWED:
*val = !chg->flash_active;
break;
case PSY_IIO_QC_OPTI_DISABLE:
if (chg->hw_die_temp_mitigation)
*val = QC_THERMAL_BALANCE_DISABLE
| QC_INOV_THERMAL_DISABLE;
if (chg->hw_connector_mitigation)
*val |= QC_CTM_DISABLE;
break;
case PSY_IIO_VOLTAGE_VPH:
rc = smblib_get_prop_vph_voltage_now(chg, val);
break;
case PSY_IIO_THERM_ICL_LIMIT:
*val = get_client_vote(chg->usb_icl_votable,
THERMAL_THROTTLE_VOTER);
break;
case PSY_IIO_ADAPTER_CC_MODE:
*val = chg->adapter_cc_mode;
break;
case PSY_IIO_SKIN_HEALTH:
*val = smblib_get_skin_temp_status(chg);
break;
case PSY_IIO_APSD_RERUN:
*val = 0;
break;
case PSY_IIO_APSD_TIMEOUT:
*val = chg->apsd_ext_timeout;
break;
case PSY_IIO_CHARGER_STATUS:
*val = 0;
if (chg->sdam_base) {
rc = smblib_read(chg,
chg->sdam_base + SDAM_QC_DET_STATUS_REG, &reg);
if (!rc)
*val = reg;
}
break;
case PSY_IIO_USB_INPUT_VOLTAGE_SETTLED:
*val = 0;
if (chg->sdam_base) {
rc = smblib_batch_read(chg,
chg->sdam_base + SDAM_QC_ADC_LSB_REG, buff, 2);
if (!rc)
*val = (buff[1] << 8 | buff[0]) * 1038;
}
break;
/* MAIN */
case PSY_IIO_MAIN_INPUT_CURRENT_SETTLED:
rc = smblib_get_prop_input_current_settled(chg, &pval);
if (!rc)
*val = pval.intval;
break;
case PSY_IIO_MAIN_INPUT_VOLTAGE_SETTLED:
rc = smblib_get_prop_input_voltage_settled(chg, val);
break;
case PSY_IIO_FCC_DELTA:
rc = smblib_get_prop_fcc_delta(chg, val);
break;
case PSY_IIO_FLASH_ACTIVE:
*val = chg->flash_active;
break;
case PSY_IIO_FLASH_TRIGGER:
*val = 0;
if (chg->chg_param.smb_version == PMI632)
rc = schgm_flash_get_vreg_ok(chg, val);
break;
case PSY_IIO_TOGGLE_STAT:
*val = 0;
break;
case PSY_IIO_MAIN_FCC_MAX:
*val = chg->main_fcc_max;
break;
case PSY_IIO_IRQ_STATUS:
rc = smblib_get_irq_status(chg, val);
break;
case PSY_IIO_FORCE_MAIN_FCC:
rc = smblib_get_charge_param(chg, &chg->param.fcc,
val);
break;
case PSY_IIO_FORCE_MAIN_ICL:
rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
val);
break;
case PSY_IIO_COMP_CLAMP_LEVEL:
*val = chg->comp_clamp_level;
break;
/* Use this property to report overheat status */
case PSY_IIO_HOT_TEMP:
*val = chg->thermal_overheat;
break;
case PSY_IIO_VOLTAGE_MAX:
rc = smblib_get_charge_param(chg, &chg->param.fv, val);
break;
case PSY_IIO_CONSTANT_CHARGE_CURRENT_MAX:
rc = smblib_get_charge_param(chg, &chg->param.fcc,
val);
break;
case PSY_IIO_CURRENT_MAX:
rc = smblib_get_icl_current(chg, val);
break;
case PSY_IIO_HEALTH:
rc = *val = smblib_get_prop_smb_health(chg);
break;
/* DC */
case PSY_IIO_DC_REAL_TYPE:
*val = POWER_SUPPLY_TYPE_MAINS;
break;
case PSY_IIO_INPUT_VOLTAGE_REGULATION:
rc = smblib_get_prop_voltage_wls_output(chg, &pval);
if (!rc)
*val = pval.intval;
break;
case PSY_IIO_DC_RESET:
*val = 0;
break;
case PSY_IIO_AICL_DONE:
*val = chg->dcin_aicl_done;
break;
/* BATTERY */
case PSY_IIO_CHARGER_TEMP:
rc = smblib_get_prop_charger_temp(chg, val);
break;
case PSY_IIO_CHARGER_TEMP_MAX:
*val = chg->charger_temp_max;
break;
case PSY_IIO_SW_JEITA_ENABLED:
*val = chg->sw_jeita_enabled;
break;
case PSY_IIO_PARALLEL_DISABLE:
*val = get_client_vote(chg->pl_disable_votable,
USER_VOTER);
break;
case PSY_IIO_CHARGE_DONE:
rc = smblib_get_prop_batt_charge_done(chg, val);
break;
case PSY_IIO_SET_SHIP_MODE:
/* Not in ship mode as long as device is active */
*val = 0;
break;
case PSY_IIO_RERUN_AICL:
*val = 0;
break;
case PSY_IIO_DP_DM:
*val = chg->pulse_cnt;
break;
case PSY_IIO_INPUT_CURRENT_LIMITED:
rc = smblib_get_prop_input_current_limited(chg, val);
break;
case PSY_IIO_DIE_HEALTH:
rc = smblib_get_die_health(chg, val);
break;
case PSY_IIO_RECHARGE_SOC:
*val = chg->auto_recharge_soc;
break;
case PSY_IIO_FORCE_RECHARGE:
*val = 0;
break;
case PSY_IIO_FCC_STEPPER_ENABLE:
*val = chg->fcc_stepper_enable;
break;
default:
pr_err("get prop %d is not supported\n", channel);
rc = -EINVAL;
break;
}
if (rc < 0) {
pr_err("Couldn't get prop %d rc = %d\n", channel, rc);
return rc;
}
return IIO_VAL_INT;
}
int smb5_iio_set_prop(struct smb_charger *chg, int channel, int val)
{
union power_supply_propval pval = {0, };
int real_chg_type = chg->real_charger_type;
int icl, rc = 0, offset_ua = 0;
switch (channel) {
/* USB */
case PSY_IIO_PD_CURRENT_MAX:
rc = smblib_set_prop_pd_current_max(chg, val);
break;
case PSY_IIO_TYPEC_POWER_ROLE:
rc = smblib_set_prop_typec_power_role(chg, val);
break;
case PSY_IIO_TYPEC_SRC_RP:
rc = smblib_set_prop_typec_select_rp(chg, val);
break;
case PSY_IIO_PD_ACTIVE:
rc = smblib_set_prop_pd_active(chg, val);
break;
case PSY_IIO_PD_IN_HARD_RESET:
rc = smblib_set_prop_pd_in_hard_reset(chg, val);
break;
case PSY_IIO_PD_USB_SUSPEND_SUPPORTED:
chg->system_suspend_supported = val;
break;
case PSY_IIO_CTM_CURRENT_MAX:
rc = vote(chg->usb_icl_votable, CTM_VOTER,
val >= 0, val);
break;
case PSY_IIO_PR_SWAP:
rc = smblib_set_prop_pr_swap_in_progress(chg, val);
break;
case PSY_IIO_PD_VOLTAGE_MAX:
rc = smblib_set_prop_pd_voltage_max(chg, val);
break;
case PSY_IIO_PD_VOLTAGE_MIN:
rc = smblib_set_prop_pd_voltage_min(chg, val);
break;
case PSY_IIO_CONNECTOR_HEALTH:
chg->connector_health = val;
if (chg->usb_psy)
power_supply_changed(chg->usb_psy);
break;
case PSY_IIO_THERM_ICL_LIMIT:
if (!is_client_vote_enabled(chg->usb_icl_votable,
THERMAL_THROTTLE_VOTER)) {
chg->init_thermal_ua = get_effective_result(
chg->usb_icl_votable);
icl = chg->init_thermal_ua + val;
} else {
icl = get_client_vote(chg->usb_icl_votable,
THERMAL_THROTTLE_VOTER) + val;
}
if (icl >= MIN_THERMAL_VOTE_UA)
rc = vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER,
(icl != chg->init_thermal_ua), icl);
else
rc = -EINVAL;
break;
case PSY_IIO_VOLTAGE_MAX_LIMIT:
smblib_set_prop_usb_voltage_max_limit(chg, val);
break;
case PSY_IIO_ADAPTER_CC_MODE:
chg->adapter_cc_mode = val;
break;
case PSY_IIO_APSD_RERUN:
del_timer_sync(&chg->apsd_timer);
chg->apsd_ext_timeout = false;
smblib_rerun_apsd(chg);
break;
/* MAIN */
case PSY_IIO_FLASH_ACTIVE:
if ((chg->chg_param.smb_version == PMI632)
&& (chg->flash_active != val)) {
chg->flash_active = val;
rc = smblib_get_prop_usb_present(chg, &pval);
if (rc < 0)
pr_err("Failed to get USB preset status rc=%d\n",
rc);
if (pval.intval) {
rc = smblib_force_vbus_voltage(chg,
chg->flash_active ? FORCE_5V_BIT
: IDLE_BIT);
if (rc < 0)
pr_err("Failed to force 5V\n");
else
chg->pulse_cnt = 0;
} else {
/* USB absent & flash not-active - vote 100mA */
vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER,
true, SDP_100_MA);
}
pr_debug("flash active VBUS 5V restriction %s\n",
chg->flash_active ? "applied" : "removed");
/* Update userspace */
if (chg->batt_psy)
power_supply_changed(chg->batt_psy);
}
break;
case PSY_IIO_TOGGLE_STAT:
rc = smblib_toggle_smb_en(chg, val);
break;
case PSY_IIO_MAIN_FCC_MAX:
chg->main_fcc_max = val;
rerun_election(chg->fcc_votable);
break;
case PSY_IIO_FORCE_MAIN_FCC:
vote_override(chg->fcc_main_votable, CC_MODE_VOTER,
(val < 0) ? false : true, val);
if (val >= 0)
chg->chg_param.forced_main_fcc = val;
/*
* Remove low vote on FCC_MAIN, for WLS, to allow FCC_MAIN to
* rise to its full value.
*/
if (val < 0)
vote(chg->fcc_main_votable, WLS_PL_CHARGING_VOTER,
false, 0);
/* Main FCC updated re-calculate FCC */
rerun_election(chg->fcc_votable);
break;
case PSY_IIO_FORCE_MAIN_ICL:
vote_override(chg->usb_icl_votable, CC_MODE_VOTER,
(val < 0) ? false : true, val);
/* Main ICL updated re-calculate ILIM */
if (real_chg_type == QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3 ||
real_chg_type == QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3P5)
rerun_election(chg->fcc_votable);
break;
case PSY_IIO_COMP_CLAMP_LEVEL:
rc = smb5_set_prop_comp_clamp_level(chg, val);
break;
case PSY_IIO_HOT_TEMP:
rc = smblib_set_prop_thermal_overheat(chg, val);
break;
case PSY_IIO_VOLTAGE_MAX:
rc = smblib_set_charge_param(chg, &chg->param.fv, val);
break;
case PSY_IIO_CONSTANT_CHARGE_CURRENT_MAX:
/* Adjust Main FCC for QC3.0 + SMB1390 */
rc = smblib_get_qc3_main_icl_offset(chg, &offset_ua);
if (rc < 0)
offset_ua = 0;
rc = smblib_set_charge_param(chg, &chg->param.fcc,
val + offset_ua);
break;
case PSY_IIO_CURRENT_MAX:
rc = smblib_set_icl_current(chg, val);
break;
/* DC */
case PSY_IIO_INPUT_VOLTAGE_REGULATION:
pval.intval = val;
rc = smblib_set_prop_voltage_wls_output(chg, &pval);
break;
case PSY_IIO_DC_RESET:
rc = smblib_set_prop_dc_reset(chg);
break;
/* BATTERY */
case PSY_IIO_PARALLEL_DISABLE:
vote(chg->pl_disable_votable, USER_VOTER, (bool)val, 0);
break;
case PSY_IIO_SET_SHIP_MODE:
/* Not in ship mode as long as the device is active */
if (!val)
break;
if (chg->iio_chan_list_smb_parallel)
rc = iio_write_channel_raw(
chg->iio_chan_list_smb_parallel[SMB_SET_SHIP_MODE],
val);
rc = smblib_set_prop_ship_mode(chg, val);
break;
case PSY_IIO_RERUN_AICL:
rc = smblib_run_aicl(chg, RERUN_AICL);
break;
case PSY_IIO_DP_DM:
if (!chg->flash_active)
rc = smblib_dp_dm(chg, val);
break;
case PSY_IIO_INPUT_CURRENT_LIMITED:
rc = smblib_set_prop_input_current_limited(chg, val);
break;
case PSY_IIO_DIE_HEALTH:
chg->die_health = val;
if (chg->batt_psy)
power_supply_changed(chg->batt_psy);
break;
case PSY_IIO_RECHARGE_SOC:
rc = smblib_set_prop_rechg_soc_thresh(chg, val);
break;
case PSY_IIO_FORCE_RECHARGE:
/* toggle charging to force recharge */
vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
true, 0);
/* charge disable delay */
msleep(50);
vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
false, 0);
break;
case PSY_IIO_FCC_STEPPER_ENABLE:
chg->fcc_stepper_enable = val;
break;
default:
pr_err("get prop %d is not supported\n", channel);
rc = -EINVAL;
break;
}
if (rc < 0) {
pr_err("Couldn't set prop %d rc = %d\n", channel, rc);
return rc;
}
return 0;
}
struct iio_channel **get_ext_channels(struct device *dev,
const char *const *channel_map, int size)
{
int i, rc = 0;
struct iio_channel **iio_ch_ext;
iio_ch_ext = devm_kcalloc(dev, size, sizeof(*iio_ch_ext), GFP_KERNEL);
if (!iio_ch_ext)
return ERR_PTR(-ENOMEM);
for (i = 0; i < size; i++) {
iio_ch_ext[i] = devm_iio_channel_get(dev, channel_map[i]);
if (IS_ERR(iio_ch_ext[i])) {
rc = PTR_ERR(iio_ch_ext[i]);
if (rc != -EPROBE_DEFER)
dev_err(dev, "%s channel unavailable, %d\n",
channel_map[i], rc);
return ERR_PTR(rc);
}
}
return iio_ch_ext;
}

View file

@ -0,0 +1,206 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
#ifndef __SMB5_IIO_H
#define __SMB5_IIO_H
#include <linux/iio/iio.h>
#include <dt-bindings/iio/qti_power_supply_iio.h>
enum iio_type {
MAIN,
QG,
CP,
SMB_PARALLEL,
};
/* For qpnp-smb5.c and smb5-lib.c */
enum qg_chg_iio_channels {
SMB5_QG_DEBUG_BATTERY,
SMB5_QG_CAPACITY,
SMB5_QG_REAL_CAPACITY,
SMB5_QG_CC_SOC,
SMB5_QG_CURRENT_NOW,
SMB5_QG_VOLTAGE_NOW,
SMB5_QG_VOLTAGE_MAX,
SMB5_QG_CHARGE_FULL,
SMB5_QG_RESISTANCE_ID,
SMB5_QG_TEMP,
SMB5_QG_CHARGE_COUNTER,
SMB5_QG_CYCLE_COUNT,
SMB5_QG_CHARGE_FULL_DESIGN,
SMB5_QG_TIME_TO_FULL_NOW,
};
enum cp_iio_channels {
CP_PARALLEL_OUTPUT_MODE,
CP_MASTER_ENABLE,
CP_ILIM,
CP_DIE_TEMP,
};
/* For smb5-lib.c and smb5-iio.c */
enum smb_parallel_iio_channels {
SMB_CHARGER_TEMP,
SMB_CHARGER_TEMP_MAX,
SMB_SET_SHIP_MODE,
};
/* For step-chg-jeita.c */
enum step_chg_iio_channels {
STEP_QG_RESISTANCE_ID = 0,
STEP_QG_VOLTAGE_NOW,
STEP_QG_TEMP,
STEP_QG_CAPACITY,
STEP_QG_VOLTAGE_OCV,
STEP_QG_VOLTAGE_AVG,
};
/* For battery.c */
enum bat_cp_iio_channels {
BAT_CP_PARALLEL_MODE,
BAT_CP_PARALLEL_OUTPUT_MODE,
BAT_CP_MIN_ICL,
BAT_CP_SWITCHER_EN,
};
enum bat_smb_parallel_iio_channels {
BAT_SMB_PARALLEL_INPUT_SUSPEND,
BAT_SMB_PARALLEL_MODE,
BAT_SMB_PARALLEL_BATFET_MODE,
BAT_SMB_PARALLEL_MIN_ICL,
BAT_SMB_PARALLEL_FCC_MAX,
BAT_SMB_PARALLEL_CURRENT_MAX,
BAT_SMB_PARALLEL_CONSTANT_CHARGE_CURRENT_MAX,
BAT_SMB_PARALLEL_VOLTAGE_MAX,
BAT_SMB_PARALLEL_CHARGE_TYPE,
};
struct smb5_iio_prop_channels {
const char *datasheet_name;
int channel_num;
enum iio_chan_type type;
long info_mask;
};
#define PARAM(chan) PSY_IIO_##chan
#define SMB5_CHAN(_dname, _chan, _type, _mask) \
{ \
.datasheet_name = _dname, \
.channel_num = _chan, \
.type = _type, \
.info_mask = _mask, \
}, \
#define SMB5_CHAN_VOLT(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_VOLTAGE, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_CUR(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_CURRENT, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_RES(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_RESISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_TEMP(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_TEMP, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_POWER(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_POWER, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_CAP(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_CAPACITANCE, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_COUNT(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_COUNT, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_INDEX(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_INDEX, BIT(IIO_CHAN_INFO_PROCESSED)) \
#define SMB5_CHAN_ACTIVITY(_dname, chan) \
[PARAM(chan)] = SMB5_CHAN(_dname, PARAM(chan), \
IIO_ACTIVITY, BIT(IIO_CHAN_INFO_PROCESSED)) \
static const struct smb5_iio_prop_channels smb5_chans_pmic[] = {
SMB5_CHAN_CUR("usb_pd_current_max", PD_CURRENT_MAX)
SMB5_CHAN_INDEX("usb_typec_mode", TYPEC_MODE)
SMB5_CHAN_INDEX("usb_typec_power_role", TYPEC_POWER_ROLE)
SMB5_CHAN_INDEX("usb_typec_cc_orientation", TYPEC_CC_ORIENTATION)
SMB5_CHAN_INDEX("usb_pd_active", PD_ACTIVE)
SMB5_CHAN_CUR("usb_input_current_settled", USB_INPUT_CURRENT_SETTLED)
SMB5_CHAN_ACTIVITY("usb_pe_start", PE_START)
SMB5_CHAN_CUR("usb_ctm_current_max", CTM_CURRENT_MAX)
SMB5_CHAN_CUR("usb_hw_current_max", HW_CURRENT_MAX)
SMB5_CHAN_INDEX("usb_real_type", USB_REAL_TYPE)
SMB5_CHAN_VOLT("usb_pd_voltage_max", PD_VOLTAGE_MAX)
SMB5_CHAN_VOLT("usb_pd_voltage_min", PD_VOLTAGE_MIN)
SMB5_CHAN_INDEX("usb_connector_type", CONNECTOR_TYPE)
SMB5_CHAN_INDEX("usb_connector_health", CONNECTOR_HEALTH)
SMB5_CHAN_VOLT("usb_voltage_max_limit", VOLTAGE_MAX_LIMIT)
SMB5_CHAN_INDEX("usb_smb_en_mode", SMB_EN_MODE)
SMB5_CHAN_INDEX("usb_smb_en_reason", SMB_EN_REASON)
SMB5_CHAN_INDEX("usb_adapter_cc_mode", ADAPTER_CC_MODE)
SMB5_CHAN_INDEX("usb_moisture_detected", MOISTURE_DETECTED)
SMB5_CHAN_INDEX("usb_hvdcp_opti_allowed", HVDCP_OPTI_ALLOWED)
SMB5_CHAN_ACTIVITY("usb_qc_opti_disable", QC_OPTI_DISABLE)
SMB5_CHAN_VOLT("usb_voltage_vph", VOLTAGE_VPH)
SMB5_CHAN_CUR("usb_therm_icl_limit", THERM_ICL_LIMIT)
SMB5_CHAN_INDEX("usb_skin_health", SKIN_HEALTH)
SMB5_CHAN_ACTIVITY("usb_apsd_rerun", APSD_RERUN)
SMB5_CHAN_COUNT("usb_apsd_timeout", APSD_TIMEOUT)
SMB5_CHAN_INDEX("usb_charger_status", CHARGER_STATUS)
SMB5_CHAN_VOLT("usb_input_voltage_settled", USB_INPUT_VOLTAGE_SETTLED)
SMB5_CHAN_ACTIVITY("usb_typec_src_rp", TYPEC_SRC_RP)
SMB5_CHAN_ACTIVITY("usb_pd_in_hard_reset", PD_IN_HARD_RESET)
SMB5_CHAN_INDEX("usb_pd_usb_suspend_supported",
PD_USB_SUSPEND_SUPPORTED)
SMB5_CHAN_ACTIVITY("usb_pr_swap", PR_SWAP)
SMB5_CHAN_CUR("main_input_current_settled", MAIN_INPUT_CURRENT_SETTLED)
SMB5_CHAN_VOLT("main_input_voltage_settled", MAIN_INPUT_VOLTAGE_SETTLED)
SMB5_CHAN_CUR("main_fcc_delta", FCC_DELTA)
SMB5_CHAN_ACTIVITY("main_flash_active", FLASH_ACTIVE)
SMB5_CHAN_ACTIVITY("main_flash_trigger", FLASH_TRIGGER)
SMB5_CHAN_ACTIVITY("main_toggle_stat", TOGGLE_STAT)
SMB5_CHAN_CUR("main_fcc_max", MAIN_FCC_MAX)
SMB5_CHAN_INDEX("main_irq_status", IRQ_STATUS)
SMB5_CHAN_ACTIVITY("main_force_main_fcc", FORCE_MAIN_FCC)
SMB5_CHAN_ACTIVITY("main_force_main_icl", FORCE_MAIN_ICL)
SMB5_CHAN_INDEX("main_comp_clamp_level", COMP_CLAMP_LEVEL)
SMB5_CHAN_TEMP("main_temp_hot", HOT_TEMP)
SMB5_CHAN_VOLT("main_voltage_max", VOLTAGE_MAX)
SMB5_CHAN_CUR("main_constant_charge_current_max",
CONSTANT_CHARGE_CURRENT_MAX)
SMB5_CHAN_CUR("main_current_max", CURRENT_MAX)
SMB5_CHAN_INDEX("main_health", HEALTH)
SMB5_CHAN_VOLT("dc_input_voltage_regulation", INPUT_VOLTAGE_REGULATION)
SMB5_CHAN_INDEX("dc_real_type", DC_REAL_TYPE)
SMB5_CHAN_ACTIVITY("dc_reset", DC_RESET)
SMB5_CHAN_ACTIVITY("dc_aicl_done", AICL_DONE)
SMB5_CHAN_TEMP("battery_charger_temp", CHARGER_TEMP)
SMB5_CHAN_TEMP("battery_charger_temp_max", CHARGER_TEMP_MAX)
SMB5_CHAN_CUR("battery_input_current_limited", INPUT_CURRENT_LIMITED)
SMB5_CHAN_ACTIVITY("battery_sw_jeita_enabled", SW_JEITA_ENABLED)
SMB5_CHAN_ACTIVITY("battery_charge_done", CHARGE_DONE)
SMB5_CHAN_ACTIVITY("battery_parallel_disable", PARALLEL_DISABLE)
SMB5_CHAN_ACTIVITY("battery_set_ship_mode", SET_SHIP_MODE)
SMB5_CHAN_INDEX("battery_die_health", DIE_HEALTH)
SMB5_CHAN_ACTIVITY("battery_rerun_aicl", RERUN_AICL)
SMB5_CHAN_COUNT("battery_dp_dm", DP_DM)
SMB5_CHAN_ACTIVITY("battery_recharge_soc", RECHARGE_SOC)
SMB5_CHAN_ACTIVITY("battery_force_recharge", FORCE_RECHARGE)
SMB5_CHAN_ACTIVITY("battery_fcc_stepper_enable", FCC_STEPPER_ENABLE)
};
struct iio_channel **get_ext_channels(struct device *dev,
const char *const *channel_map, int size);
#endif

File diff suppressed because it is too large Load diff

View file

@ -16,6 +16,7 @@
#include <linux/regulator/consumer.h>
#include <linux/extcon-provider.h>
#include <linux/usb/typec.h>
#include <linux/qti_power_supply.h>
#include "storm-watch.h"
#include "battery.h"
@ -373,6 +374,13 @@ struct smb_iio {
struct iio_channel *smb_temp_chan;
};
enum pmic_type {
PM8150B,
PM7250B,
PM6150,
PMI632,
};
struct smb_charger {
struct device *dev;
char *name;
@ -380,6 +388,10 @@ struct smb_charger {
struct smb_irq_info *irq_info;
struct smb_params param;
struct smb_iio iio;
struct iio_channel *iio_chans;
struct iio_channel **iio_chan_list_qg;
struct iio_channel **iio_chan_list_cp;
struct iio_channel **iio_chan_list_smb_parallel;
int *debug_mask;
int pd_disabled;
enum smb_mode mode;
@ -403,12 +415,8 @@ struct smb_charger {
struct power_supply *batt_psy;
struct power_supply *usb_psy;
struct power_supply *dc_psy;
struct power_supply *bms_psy;
struct power_supply *usb_main_psy;
struct power_supply *usb_port_psy;
struct power_supply *wls_psy;
struct power_supply *cp_psy;
enum power_supply_type real_charger_type;
/* notifiers */
struct notifier_block nb;
@ -585,6 +593,7 @@ struct smb_charger {
bool qc3p5_detected;
/* workaround flag */
int real_charger_type;
u32 wa_flags;
int boost_current_ua;
int qc2_max_pulses;
@ -626,24 +635,13 @@ int smblib_batch_read(struct smb_charger *chg, u16 addr, u8 *val, int count);
int smblib_get_charge_param(struct smb_charger *chg,
struct smb_chg_param *param, int *val_u);
int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend);
int smblib_get_aicl_cont_threshold(struct smb_chg_param *param, u8 val_raw);
int smblib_enable_charging(struct smb_charger *chg, bool enable);
int smblib_set_charge_param(struct smb_charger *chg,
struct smb_chg_param *param, int val_u);
int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend);
int smblib_set_dc_suspend(struct smb_charger *chg, bool suspend);
int smblib_mapping_soc_from_field_value(struct smb_chg_param *param,
int val_u, u8 *val_raw);
int smblib_mapping_cc_delta_to_field_value(struct smb_chg_param *param,
u8 val_raw);
int smblib_mapping_cc_delta_from_field_value(struct smb_chg_param *param,
int val_u, u8 *val_raw);
int smblib_set_chg_freq(struct smb_chg_param *param,
int val_u, u8 *val_raw);
int smblib_set_prop_boost_current(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_aicl_cont_threshold(struct smb_chg_param *param,
int val_u, u8 *val_raw);
int smblib_vbus_regulator_enable(struct regulator_dev *rdev);
@ -675,7 +673,7 @@ irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data);
irqreturn_t temp_change_irq_handler(int irq, void *data);
irqreturn_t usbin_ov_irq_handler(int irq, void *data);
irqreturn_t sdam_sts_change_irq_handler(int irq, void *data);
int smblib_get_prop_input_suspend(struct smb_charger *chg,
int smblib_get_prop_input_current_limit_usb(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_batt_present(struct smb_charger *chg,
union power_supply_propval *val);
@ -686,7 +684,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
int smblib_get_prop_batt_charge_type(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_batt_current_now(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_batt_health(struct smb_charger *chg,
@ -696,11 +694,11 @@ int smblib_get_prop_system_temp_level(struct smb_charger *chg,
int smblib_get_prop_system_temp_level_max(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_input_current_limited(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_batt_iterm(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_set_prop_input_suspend(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_input_current_limit_usb(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_batt_capacity(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_batt_status(struct smb_charger *chg,
@ -708,7 +706,7 @@ int smblib_set_prop_batt_status(struct smb_charger *chg,
int smblib_set_prop_system_temp_level(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_input_current_limited(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_get_prop_dc_present(struct smb_charger *chg,
union power_supply_propval *val);
@ -718,14 +716,8 @@ int smblib_get_prop_dc_current_max(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_set_prop_dc_current_max(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_get_prop_dc_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_dc_voltage_max(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_voltage_wls_output(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_set_prop_voltage_wls_output(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_dc_reset(struct smb_charger *chg);
int smblib_get_prop_usb_present(struct smb_charger *chg,
union power_supply_propval *val);
@ -740,7 +732,7 @@ int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_set_prop_usb_voltage_max_limit(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_low_power(struct smb_charger *chg,
@ -748,60 +740,61 @@ int smblib_get_prop_low_power(struct smb_charger *chg,
int smblib_get_prop_usb_current_now(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_usb_prop_typec_mode(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_scope(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_typec_select_rp(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_typec_power_role(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_input_current_settled(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_pe_start(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_charger_temp(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_die_health(struct smb_charger *chg);
int *val);
int smblib_get_die_health(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_prop_smb_health(struct smb_charger *chg);
int smblib_get_prop_connector_health(struct smb_charger *chg);
int smblib_set_prop_thermal_overheat(struct smb_charger *chg,
int therm_overheat);
int smblib_get_skin_temp_status(struct smb_charger *chg);
int smblib_get_prop_vph_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smb5_set_prop_comp_clamp_level(struct smb_charger *chg,
int val);
int smblib_set_prop_pd_current_max(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_sdp_current_max(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_pd_voltage_max(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_pd_voltage_min(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_typec_power_role(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_typec_select_rp(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_pd_active(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_ship_mode(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_set_prop_rechg_soc_thresh(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
void smblib_suspend_on_debug_battery(struct smb_charger *chg);
int smblib_rerun_apsd_if_required(struct smb_charger *chg);
void smblib_rerun_apsd(struct smb_charger *chg);
int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_thermal_threshold(struct smb_charger *chg, u16 addr, int *val);
int smblib_dp_dm(struct smb_charger *chg, int val);
int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable);
@ -810,18 +803,15 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua);
int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua);
int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua);
int smblib_get_prop_pr_swap_in_progress(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
const union power_supply_propval *val);
int val);
int smblib_typec_port_type_set(const struct typec_capability *cap,
enum typec_port_type type);
int smblib_get_prop_from_bms(struct smb_charger *chg,
enum power_supply_property psp,
union power_supply_propval *val);
int channel, int *val);
int smblib_get_iio_channel(struct smb_charger *chg, const char *propname,
struct iio_channel **chan);
int smblib_read_iio_channel(struct smb_charger *chg, struct iio_channel *chan,
int div, int *data);
int smblib_configure_hvdcp_apsd(struct smb_charger *chg, bool enable);
int smblib_icl_override(struct smb_charger *chg, enum icl_override_mode mode);
enum alarmtimer_restart smblib_lpd_recheck_timer(struct alarm *alarm,
@ -833,9 +823,19 @@ void smblib_hvdcp_exit_config(struct smb_charger *chg);
void smblib_apsd_enable(struct smb_charger *chg, bool enable);
int smblib_force_vbus_voltage(struct smb_charger *chg, u8 val);
int smblib_get_irq_status(struct smb_charger *chg,
union power_supply_propval *val);
int *val);
int smblib_get_qc3_main_icl_offset(struct smb_charger *chg, int *offset_ua);
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
int smb5_iio_get_prop(struct smb_charger *chg, int channel, int *val);
int smb5_iio_set_prop(struct smb_charger *chg, int channel, int val);
int smblib_set_prop_voltage_wls_output(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_voltage_wls_output(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_dc_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
#endif /* __SMB5_CHARGER_H */

View file

@ -11,6 +11,8 @@
#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/pmic-voter.h>
#include <linux/iio/consumer.h>
#include <dt-bindings/iio/qti_power_supply_iio.h>
#include "step-chg-jeita.h"
#include "battery-profile-loader.h"
@ -67,12 +69,13 @@ struct step_chg_info {
struct votable *usb_icl_votable;
struct wakeup_source *step_chg_ws;
struct power_supply *batt_psy;
struct power_supply *bms_psy;
struct power_supply *usb_psy;
struct power_supply *dc_psy;
struct delayed_work status_change_work;
struct delayed_work get_config_work;
struct notifier_block nb;
struct iio_channel *iio_chans;
struct iio_channel **iio_chan_list_qg;
};
static struct step_chg_info *the_chip;
@ -95,14 +98,38 @@ static bool is_batt_available(struct step_chg_info *chip)
return true;
}
static const char * const step_chg_ext_iio_chan[] = {
[STEP_QG_RESISTANCE_ID] = "resistance_id",
[STEP_QG_VOLTAGE_NOW] = "voltage_now",
[STEP_QG_TEMP] = "temp",
[STEP_QG_CAPACITY] = "capacity",
[STEP_QG_VOLTAGE_OCV] = "voltage_ocv",
[STEP_QG_VOLTAGE_AVG] = "voltage_avg",
};
static bool is_bms_available(struct step_chg_info *chip)
{
if (!chip->bms_psy)
chip->bms_psy = power_supply_get_by_name("bms");
int rc = 0;
struct iio_channel **iio_list;
if (!chip->bms_psy)
if (IS_ERR(chip->iio_chan_list_qg))
return false;
if (!chip->iio_chan_list_qg) {
iio_list = get_ext_channels(chip->dev, step_chg_ext_iio_chan,
ARRAY_SIZE(step_chg_ext_iio_chan));
if (IS_ERR(iio_list)) {
rc = PTR_ERR(iio_list);
if (rc != -EPROBE_DEFER) {
dev_err(chip->dev, "Failed to get channels, %d\n",
rc);
chip->iio_chan_list_qg = ERR_PTR(-EINVAL);
}
return false;
}
chip->iio_chan_list_qg = iio_list;
}
return true;
}
@ -150,7 +177,7 @@ static bool is_input_present(struct step_chg_info *chip)
return false;
}
int read_range_data_from_node(struct device_node *node,
static int read_range_data_from_node(struct device_node *node,
const char *prop_str, struct range_data *ranges,
int max_threshold, u32 max_value)
{
@ -221,7 +248,32 @@ clean:
memset(ranges, 0, tuples * sizeof(struct range_data));
return rc;
}
EXPORT_SYMBOL(read_range_data_from_node);
static int step_chg_read_iio_prop(struct step_chg_info *chip,
enum iio_type type, int iio_chan, int *val)
{
struct iio_channel *iio_chan_list;
int rc;
switch (type) {
case MAIN:
if (!chip->iio_chans)
return -ENODEV;
iio_chan_list = &chip->iio_chans[iio_chan];
break;
case QG:
if (IS_ERR_OR_NULL(chip->iio_chan_list_qg))
return -ENODEV;
iio_chan_list = chip->iio_chan_list_qg[iio_chan];
break;
default:
pr_err_ratelimited("iio_type %d is not supported\n", type);
return -EINVAL;
}
rc = iio_read_channel_processed(iio_chan_list, val);
return (rc < 0) ? rc : 0;
}
static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
{
@ -229,8 +281,7 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
u32 max_fv_uv, max_fcc_ma;
const char *batt_type_str;
const __be32 *handle;
int batt_id_ohms, rc;
union power_supply_propval prop = {0, };
int batt_id_ohms = 0, rc;
handle = of_get_property(chip->dev->of_node,
"qcom,battery-data", NULL);
@ -248,9 +299,10 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
if (!is_bms_available(chip))
return -ENODEV;
power_supply_get_property(chip->bms_psy,
POWER_SUPPLY_PROP_RESISTANCE_ID, &prop);
batt_id_ohms = prop.intval;
rc = step_chg_read_iio_prop(chip, QG, STEP_QG_RESISTANCE_ID,
&batt_id_ohms);
if (rc < 0)
pr_err("Failed to read batt_id rc=%d\n", rc);
/* bms_psy has not yet read the batt_id */
if (batt_id_ohms < 0)
@ -296,6 +348,7 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
if (chip->soc_based_step_chg) {
chip->step_chg_config->param.psy_prop =
POWER_SUPPLY_PROP_CAPACITY;
chip->step_chg_config->param.iio_prop = STEP_QG_CAPACITY;
chip->step_chg_config->param.prop_name = "SOC";
chip->step_chg_config->param.hysteresis = 0;
}
@ -305,6 +358,7 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
if (chip->ocv_based_step_chg) {
chip->step_chg_config->param.psy_prop =
POWER_SUPPLY_PROP_VOLTAGE_OCV;
chip->step_chg_config->param.iio_prop = STEP_QG_VOLTAGE_OCV;
chip->step_chg_config->param.prop_name = "OCV";
chip->step_chg_config->param.hysteresis = 0;
chip->step_chg_config->param.use_bms = true;
@ -316,6 +370,7 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
if (chip->vbat_avg_based_step_chg) {
chip->step_chg_config->param.psy_prop =
POWER_SUPPLY_PROP_VOLTAGE_AVG;
chip->step_chg_config->param.iio_prop = STEP_QG_VOLTAGE_AVG;
chip->step_chg_config->param.prop_name = "VBAT_AVG";
chip->step_chg_config->param.hysteresis = 0;
chip->step_chg_config->param.use_bms = true;
@ -370,7 +425,7 @@ static void get_config_work(struct work_struct *work)
if (rc == -ENODEV || rc == -EBUSY) {
if (chip->get_config_retry_count++
< GET_CONFIG_RETRY_COUNT) {
pr_debug("bms_psy is not ready, retry: %d\n",
pr_debug("bms is not ready, retry: %d\n",
chip->get_config_retry_count);
goto reschedule;
}
@ -538,22 +593,19 @@ static int handle_step_chg_config(struct step_chg_info *chip)
if (elapsed_us < STEP_CHG_HYSTERISIS_DELAY_US)
return 0;
rc = power_supply_get_property(chip->batt_psy,
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED, &pval);
if (rc < 0)
chip->step_chg_enable = false;
else
chip->step_chg_enable = pval.intval;
if (!chip->step_chg_enable || !chip->step_chg_cfg_valid) {
if (chip->fcc_votable)
vote(chip->fcc_votable, STEP_CHG_VOTER, false, 0);
goto update_time;
}
if (chip->step_chg_config->param.use_bms)
rc = power_supply_get_property(chip->bms_psy,
chip->step_chg_config->param.psy_prop, &pval);
if (chip->step_chg_config->param.use_bms) {
rc = step_chg_read_iio_prop(chip, QG,
chip->step_chg_config->param.iio_prop, &pval.intval);
if (rc < 0)
pr_err("Failed to read IIO prop %d rc=%d\n",
chip->step_chg_config->param.iio_prop, rc);
}
else
rc = power_supply_get_property(chip->batt_psy,
chip->step_chg_config->param.psy_prop, &pval);
@ -612,15 +664,17 @@ update_time:
static int handle_jeita(struct step_chg_info *chip)
{
union power_supply_propval pval = {0, };
int rc = 0, fcc_ua = 0, fv_uv = 0;
int rc = 0, fcc_ua = 0, fv_uv = 0, data;
u64 elapsed_us;
rc = power_supply_get_property(chip->batt_psy,
POWER_SUPPLY_PROP_SW_JEITA_ENABLED, &pval);
if (rc < 0)
rc = step_chg_read_iio_prop(chip, MAIN, PSY_IIO_SW_JEITA_ENABLED,
&data);
if (rc < 0) {
chip->sw_jeita_enable = false;
else
chip->sw_jeita_enable = pval.intval;
pr_err("Failed to read jeita_enabled rc=%d\n", rc);
} else {
chip->sw_jeita_enable = data;
}
if (!chip->sw_jeita_enable || !chip->sw_jeita_cfg_valid) {
if (chip->fcc_votable)
@ -637,12 +691,16 @@ static int handle_jeita(struct step_chg_info *chip)
if (elapsed_us < STEP_CHG_HYSTERISIS_DELAY_US)
return 0;
if (chip->jeita_fcc_config->param.use_bms)
rc = power_supply_get_property(chip->bms_psy,
chip->jeita_fcc_config->param.psy_prop, &pval);
else
if (chip->jeita_fcc_config->param.use_bms) {
rc = step_chg_read_iio_prop(chip, QG,
chip->jeita_fcc_config->param.iio_prop, &pval.intval);
if (rc < 0)
pr_err("Failed to read IIO prop %d rc=%d\n",
chip->jeita_fcc_config->param.iio_prop, rc);
} else {
rc = power_supply_get_property(chip->batt_psy,
chip->jeita_fcc_config->param.psy_prop, &pval);
}
if (rc < 0) {
pr_err("Couldn't read %s property rc=%d\n",
@ -805,8 +863,6 @@ static int step_chg_notifier_call(struct notifier_block *nb,
}
if ((strcmp(psy->desc->name, "bms") == 0)) {
if (chip->bms_psy == NULL)
chip->bms_psy = psy;
if (!chip->config_is_read)
schedule_delayed_work(&chip->get_config_work, 0);
}
@ -828,8 +884,8 @@ static int step_chg_register_notifier(struct step_chg_info *chip)
return 0;
}
int qcom_step_chg_init(struct device *dev,
bool step_chg_enable, bool sw_jeita_enable, bool jeita_arb_en)
int qcom_step_chg_init(struct device *dev, bool step_chg_enable,
bool sw_jeita_enable, bool jeita_arb_en, struct iio_channel *iio_chans)
{
int rc;
struct step_chg_info *chip;
@ -843,7 +899,7 @@ int qcom_step_chg_init(struct device *dev,
if (!chip)
return -ENOMEM;
chip->step_chg_ws = wakeup_source_register("qcom-step-chg");
chip->step_chg_ws = wakeup_source_register(dev, "qcom-step-chg");
if (!chip->step_chg_ws)
return -EINVAL;
@ -854,6 +910,8 @@ int qcom_step_chg_init(struct device *dev,
chip->step_index = -EINVAL;
chip->jeita_fcc_index = -EINVAL;
chip->jeita_fv_index = -EINVAL;
chip->iio_chans = iio_chans;
chip->iio_chan_list_qg = NULL;
chip->step_chg_config = devm_kzalloc(dev,
sizeof(struct step_chg_cfg), GFP_KERNEL);
@ -861,6 +919,7 @@ int qcom_step_chg_init(struct device *dev,
return -ENOMEM;
chip->step_chg_config->param.psy_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
chip->step_chg_config->param.iio_prop = STEP_QG_VOLTAGE_NOW;
chip->step_chg_config->param.prop_name = "VBATT";
chip->step_chg_config->param.hysteresis = 100000;
@ -872,9 +931,11 @@ int qcom_step_chg_init(struct device *dev,
return -ENOMEM;
chip->jeita_fcc_config->param.psy_prop = POWER_SUPPLY_PROP_TEMP;
chip->jeita_fcc_config->param.iio_prop = STEP_QG_TEMP;
chip->jeita_fcc_config->param.prop_name = "BATT_TEMP";
chip->jeita_fcc_config->param.hysteresis = 10;
chip->jeita_fv_config->param.psy_prop = POWER_SUPPLY_PROP_TEMP;
chip->jeita_fv_config->param.iio_prop = STEP_QG_TEMP;
chip->jeita_fv_config->param.prop_name = "BATT_TEMP";
chip->jeita_fv_config->param.hysteresis = 10;

View file

@ -6,10 +6,14 @@
#ifndef __STEP_CHG_H__
#define __STEP_CHG_H__
#include <linux/iio/consumer.h>
#include "smb5-iio.h"
#define MAX_STEP_CHG_ENTRIES 8
struct step_chg_jeita_param {
u32 psy_prop;
u32 iio_prop;
char *prop_name;
int hysteresis;
bool use_bms;
@ -21,10 +25,7 @@ struct range_data {
u32 value;
};
int qcom_step_chg_init(struct device *dev,
bool step_chg_enable, bool sw_jeita_enable, bool jeita_arb_en);
int qcom_step_chg_init(struct device *dev, bool step_chg_enable,
bool sw_jeita_enable, bool jeita_arb_en, struct iio_channel *iio_chans);
void qcom_step_chg_deinit(void);
int read_range_data_from_node(struct device_node *node,
const char *prop_str, struct range_data *ranges,
int max_threshold, u32 max_value);
#endif /* __STEP_CHG_H__ */

View file

@ -0,0 +1,117 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
#ifndef __QTI_POWER_SUPPLY_H_
#define __QTI_POWER_SUPPLY_H_
#define QTI_POWER_SUPPLY_CHARGE_TYPE_TAPER 7
#define QTI_POWER_SUPPLY_TYPE_USB_HVDCP 20
#define QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3 21
#define QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3P5 22
#define QTI_POWER_SUPPLY_TYPE_USB_FLOAT 23
enum {
QTI_POWER_SUPPLY_CHARGER_SEC_NONE = 0,
QTI_POWER_SUPPLY_CHARGER_SEC_CP,
QTI_POWER_SUPPLY_CHARGER_SEC_PL,
QTI_POWER_SUPPLY_CHARGER_SEC_CP_PL,
};
enum {
QTI_POWER_SUPPLY_CP_NONE = 0,
QTI_POWER_SUPPLY_CP_HVDCP3,
QTI_POWER_SUPPLY_CP_HVDCP3P5,
QTI_POWER_SUPPLY_CP_PPS,
QTI_POWER_SUPPLY_CP_WIRELESS,
};
enum {
QTI_POWER_SUPPLY_CONNECTOR_TYPEC,
QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB,
};
enum {
QC_CTM_DISABLE = BIT(0),
QC_THERMAL_BALANCE_DISABLE = BIT(1),
QC_INOV_THERMAL_DISABLE = BIT(2),
};
enum {
QTI_POWER_SUPPLY_PD_INACTIVE = 0,
QTI_POWER_SUPPLY_PD_ACTIVE,
QTI_POWER_SUPPLY_PD_PPS_ACTIVE,
};
enum {
QTI_POWER_SUPPLY_DP_DM_UNKNOWN = 0,
QTI_POWER_SUPPLY_DP_DM_PREPARE = 1,
QTI_POWER_SUPPLY_DP_DM_UNPREPARE = 2,
QTI_POWER_SUPPLY_DP_DM_CONFIRMED_HVDCP3 = 3,
QTI_POWER_SUPPLY_DP_DM_DP_PULSE = 4,
QTI_POWER_SUPPLY_DP_DM_DM_PULSE = 5,
QTI_POWER_SUPPLY_DP_DM_DP0P6_DMF = 6,
QTI_POWER_SUPPLY_DP_DM_DP0P6_DM3P3 = 7,
QTI_POWER_SUPPLY_DP_DM_DPF_DMF = 8,
QTI_POWER_SUPPLY_DP_DM_DPR_DMR = 9,
QTI_POWER_SUPPLY_DP_DM_HVDCP3_SUPPORTED = 10,
QTI_POWER_SUPPLY_DP_DM_ICL_DOWN = 11,
QTI_POWER_SUPPLY_DP_DM_ICL_UP = 12,
QTI_POWER_SUPPLY_DP_DM_FORCE_5V = 13,
QTI_POWER_SUPPLY_DP_DM_FORCE_9V = 14,
QTI_POWER_SUPPLY_DP_DM_FORCE_12V = 15,
QTI_POWER_SUPPLY_DP_DM_CONFIRMED_HVDCP3P5 = 16,
};
/* Indicates USB Type-C CC connection status */
enum power_supply_typec_mode {
QTI_POWER_SUPPLY_TYPEC_NONE,
/* Acting as source */
QTI_POWER_SUPPLY_TYPEC_SINK, /* Rd only */
QTI_POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE, /* Rd/Ra */
QTI_POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY,/* Rd/Rd */
QTI_POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER, /* Ra/Ra */
QTI_POWER_SUPPLY_TYPEC_POWERED_CABLE_ONLY, /* Ra only */
/* Acting as sink */
QTI_POWER_SUPPLY_TYPEC_SOURCE_DEFAULT, /* Rp default */
QTI_POWER_SUPPLY_TYPEC_SOURCE_MEDIUM, /* Rp 1.5A */
QTI_POWER_SUPPLY_TYPEC_SOURCE_HIGH, /* Rp 3A */
QTI_POWER_SUPPLY_TYPEC_NON_COMPLIANT,
};
enum power_supply_typec_src_rp {
QTI_POWER_SUPPLY_TYPEC_SRC_RP_STD,
QTI_POWER_SUPPLY_TYPEC_SRC_RP_1P5A,
QTI_POWER_SUPPLY_TYPEC_SRC_RP_3A
};
/* Parallel output connection topology */
enum {
QTI_POWER_SUPPLY_PL_OUTPUT_NONE,
QTI_POWER_SUPPLY_PL_OUTPUT_VPH,
QTI_POWER_SUPPLY_PL_OUTPUT_VBAT,
};
enum {
QTI_POWER_SUPPLY_PL_NONE,
QTI_POWER_SUPPLY_PL_USBIN_USBIN,
QTI_POWER_SUPPLY_PL_USBIN_USBIN_EXT,
QTI_POWER_SUPPLY_PL_USBMID_USBMID,
};
enum {
QTI_POWER_SUPPLY_PL_STACKED_BATFET,
QTI_POWER_SUPPLY_PL_NON_STACKED_BATFET,
};
enum power_supply_typec_power_role {
QTI_POWER_SUPPLY_TYPEC_PR_NONE, /* CC lines in high-Z */
QTI_POWER_SUPPLY_TYPEC_PR_DUAL,
QTI_POWER_SUPPLY_TYPEC_PR_SINK,
QTI_POWER_SUPPLY_TYPEC_PR_SOURCE,
};
#endif /* __QTI_POWER_SUPPLY_H_ */