mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-06 03:45:24 -04:00
power: supply: qcom: Add snapshot of SMB5 charger driver
Add snapshot of qpnp-smb5 charger driver from msm-4.19
as of commit 1bb7bbeb1d09("sched: Fix compilation errors
with !WALT").
Change-Id: Ie7c99bea8887dcb97244e43e7984e2a82d1e5526
Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
This commit is contained in:
parent
3be2db0032
commit
58bfbabe9e
14 changed files with 16889 additions and 0 deletions
|
|
@ -15,4 +15,17 @@ config QPNP_QG
|
|||
to determine the battery state-of-charge (SOC) and supports other
|
||||
battery management features.
|
||||
|
||||
config QPNP_SMB5
|
||||
tristate "SMB5 Battery Charger"
|
||||
depends on MFD_SPMI_PMIC
|
||||
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
|
||||
as fuel gauge, USB, and USB-PD.
|
||||
VBUS and VCONN regulators are registered for supporting OTG,
|
||||
and powered Type-C cables respectively.
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
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
|
||||
|
|
|
|||
2118
drivers/power/supply/qcom/battery.c
Normal file
2118
drivers/power/supply/qcom/battery.c
Normal file
File diff suppressed because it is too large
Load diff
19
drivers/power/supply/qcom/battery.h
Normal file
19
drivers/power/supply/qcom/battery.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017, 2019-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef __BATTERY_H
|
||||
#define __BATTERY_H
|
||||
|
||||
struct charger_param {
|
||||
u32 fcc_step_delay_ms;
|
||||
u32 fcc_step_size_ua;
|
||||
u32 smb_version;
|
||||
u32 hvdcp2_max_icl_ua;
|
||||
u32 hvdcp3_max_icl_ua;
|
||||
u32 forced_main_fcc;
|
||||
};
|
||||
|
||||
int qcom_batt_init(struct charger_param *param);
|
||||
void qcom_batt_deinit(void);
|
||||
#endif /* __BATTERY_H */
|
||||
3780
drivers/power/supply/qcom/qpnp-smb5.c
Normal file
3780
drivers/power/supply/qcom/qpnp-smb5.c
Normal file
File diff suppressed because it is too large
Load diff
239
drivers/power/supply/qcom/schgm-flash.c
Normal file
239
drivers/power/supply/qcom/schgm-flash.c
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "SCHG-FLASH: %s: " fmt, __func__
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/pmic-voter.h>
|
||||
#include "smb5-lib.h"
|
||||
#include "schgm-flash.h"
|
||||
|
||||
#define IS_BETWEEN(left, right, value) \
|
||||
(((left) >= (right) && (left) >= (value) \
|
||||
&& (value) >= (right)) \
|
||||
|| ((left) <= (right) && (left) <= (value) \
|
||||
&& (value) <= (right)))
|
||||
|
||||
irqreturn_t schgm_flash_default_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct smb_irq_data *irq_data = data;
|
||||
|
||||
pr_debug("IRQ: %s\n", irq_data->name);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t schgm_flash_ilim2_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct smb_irq_data *irq_data = data;
|
||||
struct smb_charger *chg = irq_data->parent_data;
|
||||
int rc;
|
||||
|
||||
rc = smblib_write(chg, SCHGM_FLASH_S2_LATCH_RESET_CMD_REG,
|
||||
FLASH_S2_LATCH_RESET_BIT);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't reset S2_LATCH reset rc=%d\n", rc);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t schgm_flash_state_change_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct smb_irq_data *irq_data = data;
|
||||
struct smb_charger *chg = irq_data->parent_data;
|
||||
int rc;
|
||||
u8 reg;
|
||||
|
||||
rc = smblib_read(chg, SCHGM_FLASH_STATUS_3_REG, ®);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't read flash status_3 rc=%d\n", rc);
|
||||
else
|
||||
pr_debug("Flash status changed state=[%x]\n",
|
||||
(reg && FLASH_STATE_MASK));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#define FIXED_MODE 0
|
||||
#define ADAPTIVE_MODE 1
|
||||
static void schgm_flash_parse_dt(struct smb_charger *chg)
|
||||
{
|
||||
struct device_node *node = chg->dev->of_node;
|
||||
u32 val;
|
||||
int rc;
|
||||
|
||||
chg->flash_derating_soc = -EINVAL;
|
||||
rc = of_property_read_u32(node, "qcom,flash-derating-soc", &val);
|
||||
if (!rc) {
|
||||
if (IS_BETWEEN(0, 100, val))
|
||||
chg->flash_derating_soc = (val * 255) / 100;
|
||||
}
|
||||
|
||||
chg->flash_disable_soc = -EINVAL;
|
||||
rc = of_property_read_u32(node, "qcom,flash-disable-soc", &val);
|
||||
if (!rc) {
|
||||
if (IS_BETWEEN(0, 100, val))
|
||||
chg->flash_disable_soc = (val * 255) / 100;
|
||||
}
|
||||
|
||||
chg->headroom_mode = -EINVAL;
|
||||
rc = of_property_read_u32(node, "qcom,headroom-mode", &val);
|
||||
if (!rc) {
|
||||
if (IS_BETWEEN(FIXED_MODE, ADAPTIVE_MODE, val))
|
||||
chg->headroom_mode = val;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_flash_active(struct smb_charger *chg)
|
||||
{
|
||||
return chg->flash_active ? true : false;
|
||||
}
|
||||
|
||||
int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val)
|
||||
{
|
||||
int rc, vreg_state;
|
||||
u8 stat = 0;
|
||||
|
||||
if (!chg->flash_init_done)
|
||||
return -EPERM;
|
||||
|
||||
rc = smblib_read(chg, SCHGM_FLASH_STATUS_2_REG, &stat);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read FLASH STATUS_2 rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
vreg_state = !!(stat & VREG_OK_BIT);
|
||||
|
||||
/* If VREG_OK is not set check for flash error */
|
||||
if (!vreg_state) {
|
||||
rc = smblib_read(chg, SCHGM_FLASH_STATUS_3_REG, &stat);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read FLASH_STATUS_3 rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
if ((stat & FLASH_STATE_MASK) == FLASH_ERROR_VAL) {
|
||||
vreg_state = -EFAULT;
|
||||
rc = smblib_read(chg, SCHGM_FLASH_STATUS_5_REG,
|
||||
&stat);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read FLASH_STATUS_5 rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
pr_debug("Flash error: status=%x\n", stat);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* val can be one of the following:
|
||||
* 1 - VREG_OK is set.
|
||||
* 0 - VREG_OK is 0 but no Flash error.
|
||||
* -EFAULT - Flash Error is set.
|
||||
*/
|
||||
*val = vreg_state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode)
|
||||
{
|
||||
int rc;
|
||||
u8 reg;
|
||||
|
||||
/*
|
||||
* If torch is configured in default BOOST mode, skip any update in the
|
||||
* mode configuration.
|
||||
*/
|
||||
if (chg->headroom_mode == FIXED_MODE)
|
||||
return;
|
||||
|
||||
if ((mode != TORCH_BOOST_MODE) && (mode != TORCH_BUCK_MODE))
|
||||
return;
|
||||
|
||||
reg = mode;
|
||||
rc = smblib_masked_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG,
|
||||
TORCH_PRIORITY_CONTROL_BIT, reg);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't configure Torch priority control rc=%d\n",
|
||||
rc);
|
||||
|
||||
pr_debug("Torch priority changed to: %d\n", mode);
|
||||
}
|
||||
|
||||
int schgm_flash_init(struct smb_charger *chg)
|
||||
{
|
||||
int rc;
|
||||
u8 reg;
|
||||
|
||||
schgm_flash_parse_dt(chg);
|
||||
|
||||
if (chg->flash_derating_soc != -EINVAL) {
|
||||
rc = smblib_write(chg, SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG,
|
||||
chg->flash_derating_soc);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't configure SOC for flash derating rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (chg->flash_disable_soc != -EINVAL) {
|
||||
rc = smblib_write(chg, SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG,
|
||||
chg->flash_disable_soc);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't configure SOC for flash disable rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (chg->headroom_mode != -EINVAL) {
|
||||
/*
|
||||
* configure headroom management policy for
|
||||
* flash and torch mode.
|
||||
*/
|
||||
reg = (chg->headroom_mode == FIXED_MODE)
|
||||
? FORCE_FLASH_BOOST_5V_BIT : 0;
|
||||
rc = smblib_write(chg, SCHGM_FORCE_BOOST_CONTROL, reg);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't write force boost control reg rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
reg = (chg->headroom_mode == FIXED_MODE)
|
||||
? TORCH_PRIORITY_CONTROL_BIT : 0;
|
||||
rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG, reg);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't force 5V boost in torch mode rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if ((chg->flash_derating_soc != -EINVAL)
|
||||
|| (chg->flash_disable_soc != -EINVAL)) {
|
||||
/* Check if SOC based derating/disable is enabled */
|
||||
rc = smblib_read(chg, SCHGM_FLASH_CONTROL_REG, ®);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read flash control reg rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
if (!(reg & SOC_LOW_FOR_FLASH_EN_BIT))
|
||||
pr_warn("Soc based flash derating not enabled\n");
|
||||
}
|
||||
|
||||
chg->flash_init_done = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
54
drivers/power/supply/qcom/schgm-flash.h
Normal file
54
drivers/power/supply/qcom/schgm-flash.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SCHGM_FLASH_H__
|
||||
#define __SCHGM_FLASH_H__
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define SCHGM_FLASH_BASE 0xA600
|
||||
|
||||
#define SCHGM_FLASH_STATUS_2_REG (SCHGM_FLASH_BASE + 0x07)
|
||||
#define VREG_OK_BIT BIT(4)
|
||||
|
||||
#define SCHGM_FLASH_STATUS_3_REG (SCHGM_FLASH_BASE + 0x08)
|
||||
#define FLASH_STATE_MASK GENMASK(2, 0)
|
||||
#define FLASH_ERROR_VAL 0x7
|
||||
|
||||
#define SCHGM_FLASH_INT_RT_STS_REG (SCHGM_FLASH_BASE + 0x10)
|
||||
|
||||
#define SCHGM_FLASH_STATUS_5_REG (SCHGM_FLASH_BASE + 0x0B)
|
||||
|
||||
#define SCHGM_FORCE_BOOST_CONTROL (SCHGM_FLASH_BASE + 0x41)
|
||||
#define FORCE_FLASH_BOOST_5V_BIT BIT(0)
|
||||
|
||||
#define SCHGM_FLASH_S2_LATCH_RESET_CMD_REG (SCHGM_FLASH_BASE + 0x44)
|
||||
#define FLASH_S2_LATCH_RESET_BIT BIT(0)
|
||||
|
||||
#define SCHGM_FLASH_CONTROL_REG (SCHGM_FLASH_BASE + 0x60)
|
||||
#define SOC_LOW_FOR_FLASH_EN_BIT BIT(7)
|
||||
|
||||
#define SCHGM_TORCH_PRIORITY_CONTROL_REG (SCHGM_FLASH_BASE + 0x63)
|
||||
#define TORCH_PRIORITY_CONTROL_BIT BIT(0)
|
||||
|
||||
#define SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG (SCHGM_FLASH_BASE + 0x67)
|
||||
|
||||
#define SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG \
|
||||
(SCHGM_FLASH_BASE + 0x68)
|
||||
|
||||
enum torch_mode {
|
||||
TORCH_BUCK_MODE = 0,
|
||||
TORCH_BOOST_MODE,
|
||||
};
|
||||
|
||||
int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val);
|
||||
void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode);
|
||||
int schgm_flash_init(struct smb_charger *chg);
|
||||
bool is_flash_active(struct smb_charger *chg);
|
||||
|
||||
irqreturn_t schgm_flash_default_irq_handler(int irq, void *data);
|
||||
irqreturn_t schgm_flash_ilim2_irq_handler(int irq, void *data);
|
||||
irqreturn_t schgm_flash_state_change_irq_handler(int irq, void *data);
|
||||
#endif /* __SCHGM_FLASH_H__ */
|
||||
8220
drivers/power/supply/qcom/smb5-lib.c
Normal file
8220
drivers/power/supply/qcom/smb5-lib.c
Normal file
File diff suppressed because it is too large
Load diff
841
drivers/power/supply/qcom/smb5-lib.h
Normal file
841
drivers/power/supply/qcom/smb5-lib.h
Normal file
|
|
@ -0,0 +1,841 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SMB5_CHARGER_H
|
||||
#define __SMB5_CHARGER_H
|
||||
|
||||
#include <linux/alarmtimer.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/usb/typec.h>
|
||||
#include "storm-watch.h"
|
||||
#include "battery.h"
|
||||
|
||||
enum print_reason {
|
||||
PR_INTERRUPT = BIT(0),
|
||||
PR_REGISTER = BIT(1),
|
||||
PR_MISC = BIT(2),
|
||||
PR_PARALLEL = BIT(3),
|
||||
PR_OTG = BIT(4),
|
||||
PR_WLS = BIT(5),
|
||||
};
|
||||
|
||||
#define DEFAULT_VOTER "DEFAULT_VOTER"
|
||||
#define USER_VOTER "USER_VOTER"
|
||||
#define PD_VOTER "PD_VOTER"
|
||||
#define DCP_VOTER "DCP_VOTER"
|
||||
#define QC_VOTER "QC_VOTER"
|
||||
#define USB_PSY_VOTER "USB_PSY_VOTER"
|
||||
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
|
||||
#define USBIN_V_VOTER "USBIN_V_VOTER"
|
||||
#define CHG_STATE_VOTER "CHG_STATE_VOTER"
|
||||
#define TAPER_END_VOTER "TAPER_END_VOTER"
|
||||
#define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER"
|
||||
#define DIE_TEMP_VOTER "DIE_TEMP_VOTER"
|
||||
#define BOOST_BACK_VOTER "BOOST_BACK_VOTER"
|
||||
#define MICRO_USB_VOTER "MICRO_USB_VOTER"
|
||||
#define DEBUG_BOARD_VOTER "DEBUG_BOARD_VOTER"
|
||||
#define PD_SUSPEND_SUPPORTED_VOTER "PD_SUSPEND_SUPPORTED_VOTER"
|
||||
#define PL_DELAY_VOTER "PL_DELAY_VOTER"
|
||||
#define CTM_VOTER "CTM_VOTER"
|
||||
#define SW_QC3_VOTER "SW_QC3_VOTER"
|
||||
#define AICL_RERUN_VOTER "AICL_RERUN_VOTER"
|
||||
#define SW_ICL_MAX_VOTER "SW_ICL_MAX_VOTER"
|
||||
#define PL_QNOVO_VOTER "PL_QNOVO_VOTER"
|
||||
#define QNOVO_VOTER "QNOVO_VOTER"
|
||||
#define BATT_PROFILE_VOTER "BATT_PROFILE_VOTER"
|
||||
#define OTG_DELAY_VOTER "OTG_DELAY_VOTER"
|
||||
#define USBIN_I_VOTER "USBIN_I_VOTER"
|
||||
#define WEAK_CHARGER_VOTER "WEAK_CHARGER_VOTER"
|
||||
#define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER"
|
||||
#define WBC_VOTER "WBC_VOTER"
|
||||
#define HW_LIMIT_VOTER "HW_LIMIT_VOTER"
|
||||
#define PL_SMB_EN_VOTER "PL_SMB_EN_VOTER"
|
||||
#define FORCE_RECHARGE_VOTER "FORCE_RECHARGE_VOTER"
|
||||
#define LPD_VOTER "LPD_VOTER"
|
||||
#define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER"
|
||||
#define SW_THERM_REGULATION_VOTER "SW_THERM_REGULATION_VOTER"
|
||||
#define JEITA_ARB_VOTER "JEITA_ARB_VOTER"
|
||||
#define MOISTURE_VOTER "MOISTURE_VOTER"
|
||||
#define HVDCP2_ICL_VOTER "HVDCP2_ICL_VOTER"
|
||||
#define AICL_THRESHOLD_VOTER "AICL_THRESHOLD_VOTER"
|
||||
#define USBOV_DBC_VOTER "USBOV_DBC_VOTER"
|
||||
#define CHG_TERMINATION_VOTER "CHG_TERMINATION_VOTER"
|
||||
#define THERMAL_THROTTLE_VOTER "THERMAL_THROTTLE_VOTER"
|
||||
#define VOUT_VOTER "VOUT_VOTER"
|
||||
#define USB_SUSPEND_VOTER "USB_SUSPEND_VOTER"
|
||||
#define CHARGER_TYPE_VOTER "CHARGER_TYPE_VOTER"
|
||||
#define HDC_IRQ_VOTER "HDC_IRQ_VOTER"
|
||||
#define DETACH_DETECT_VOTER "DETACH_DETECT_VOTER"
|
||||
#define CC_MODE_VOTER "CC_MODE_VOTER"
|
||||
#define MAIN_FCC_VOTER "MAIN_FCC_VOTER"
|
||||
#define DCIN_AICL_VOTER "DCIN_AICL_VOTER"
|
||||
#define WLS_PL_CHARGING_VOTER "WLS_PL_CHARGING_VOTER"
|
||||
#define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER"
|
||||
#define OVERHEAT_LIMIT_VOTER "OVERHEAT_LIMIT_VOTER"
|
||||
#define TYPEC_SWAP_VOTER "TYPEC_SWAP_VOTER"
|
||||
|
||||
#define BOOST_BACK_STORM_COUNT 3
|
||||
#define WEAK_CHG_STORM_COUNT 8
|
||||
|
||||
#define VBAT_TO_VRAW_ADC(v) div_u64((u64)v * 1000000UL, 194637UL)
|
||||
|
||||
#define ITERM_LIMITS_PMI632_MA 5000
|
||||
#define ITERM_LIMITS_PM8150B_MA 10000
|
||||
#define ADC_CHG_ITERM_MASK 32767
|
||||
|
||||
#define SDP_100_MA 100000
|
||||
#define SDP_CURRENT_UA 500000
|
||||
#define CDP_CURRENT_UA 1500000
|
||||
#define DCP_CURRENT_UA 1500000
|
||||
#define HVDCP_CURRENT_UA 3000000
|
||||
#define TYPEC_DEFAULT_CURRENT_UA 900000
|
||||
#define TYPEC_MEDIUM_CURRENT_UA 1500000
|
||||
#define TYPEC_HIGH_CURRENT_UA 3000000
|
||||
#define DCIN_ICL_MIN_UA 100000
|
||||
#define DCIN_ICL_MAX_UA 1500000
|
||||
#define DCIN_ICL_STEP_UA 100000
|
||||
#define ROLE_REVERSAL_DELAY_MS 500
|
||||
|
||||
enum smb_mode {
|
||||
PARALLEL_MASTER = 0,
|
||||
PARALLEL_SLAVE,
|
||||
NUM_MODES,
|
||||
};
|
||||
|
||||
enum sink_src_mode {
|
||||
SINK_MODE,
|
||||
SRC_MODE,
|
||||
AUDIO_ACCESS_MODE,
|
||||
UNATTACHED_MODE,
|
||||
};
|
||||
|
||||
enum qc2_non_comp_voltage {
|
||||
QC2_COMPLIANT,
|
||||
QC2_NON_COMPLIANT_9V,
|
||||
QC2_NON_COMPLIANT_12V
|
||||
};
|
||||
|
||||
enum {
|
||||
BOOST_BACK_WA = BIT(0),
|
||||
SW_THERM_REGULATION_WA = BIT(1),
|
||||
WEAK_ADAPTER_WA = BIT(2),
|
||||
USBIN_OV_WA = BIT(3),
|
||||
CHG_TERMINATION_WA = BIT(4),
|
||||
USBIN_ADC_WA = BIT(5),
|
||||
SKIP_MISC_PBS_IRQ_WA = BIT(6),
|
||||
};
|
||||
|
||||
enum jeita_cfg_stat {
|
||||
JEITA_CFG_NONE = 0,
|
||||
JEITA_CFG_FAILURE,
|
||||
JEITA_CFG_COMPLETE,
|
||||
};
|
||||
|
||||
enum {
|
||||
RERUN_AICL = 0,
|
||||
RESTART_AICL,
|
||||
};
|
||||
|
||||
enum smb_irq_index {
|
||||
/* CHGR */
|
||||
CHGR_ERROR_IRQ = 0,
|
||||
CHG_STATE_CHANGE_IRQ,
|
||||
STEP_CHG_STATE_CHANGE_IRQ,
|
||||
STEP_CHG_SOC_UPDATE_FAIL_IRQ,
|
||||
STEP_CHG_SOC_UPDATE_REQ_IRQ,
|
||||
FG_FVCAL_QUALIFIED_IRQ,
|
||||
VPH_ALARM_IRQ,
|
||||
VPH_DROP_PRECHG_IRQ,
|
||||
/* DCDC */
|
||||
OTG_FAIL_IRQ,
|
||||
OTG_OC_DISABLE_SW_IRQ,
|
||||
OTG_OC_HICCUP_IRQ,
|
||||
BSM_ACTIVE_IRQ,
|
||||
HIGH_DUTY_CYCLE_IRQ,
|
||||
INPUT_CURRENT_LIMITING_IRQ,
|
||||
CONCURRENT_MODE_DISABLE_IRQ,
|
||||
SWITCHER_POWER_OK_IRQ,
|
||||
/* BATIF */
|
||||
BAT_TEMP_IRQ,
|
||||
ALL_CHNL_CONV_DONE_IRQ,
|
||||
BAT_OV_IRQ,
|
||||
BAT_LOW_IRQ,
|
||||
BAT_THERM_OR_ID_MISSING_IRQ,
|
||||
BAT_TERMINAL_MISSING_IRQ,
|
||||
BUCK_OC_IRQ,
|
||||
VPH_OV_IRQ,
|
||||
/* USB */
|
||||
USBIN_COLLAPSE_IRQ,
|
||||
USBIN_VASHDN_IRQ,
|
||||
USBIN_UV_IRQ,
|
||||
USBIN_OV_IRQ,
|
||||
USBIN_PLUGIN_IRQ,
|
||||
USBIN_REVI_CHANGE_IRQ,
|
||||
USBIN_SRC_CHANGE_IRQ,
|
||||
USBIN_ICL_CHANGE_IRQ,
|
||||
/* DC */
|
||||
DCIN_VASHDN_IRQ,
|
||||
DCIN_UV_IRQ,
|
||||
DCIN_OV_IRQ,
|
||||
DCIN_PLUGIN_IRQ,
|
||||
DCIN_REVI_IRQ,
|
||||
DCIN_PON_IRQ,
|
||||
DCIN_EN_IRQ,
|
||||
/* TYPEC */
|
||||
TYPEC_OR_RID_DETECTION_CHANGE_IRQ,
|
||||
TYPEC_VPD_DETECT_IRQ,
|
||||
TYPEC_CC_STATE_CHANGE_IRQ,
|
||||
TYPEC_VCONN_OC_IRQ,
|
||||
TYPEC_VBUS_CHANGE_IRQ,
|
||||
TYPEC_ATTACH_DETACH_IRQ,
|
||||
TYPEC_LEGACY_CABLE_DETECT_IRQ,
|
||||
TYPEC_TRY_SNK_SRC_DETECT_IRQ,
|
||||
/* MISC */
|
||||
WDOG_SNARL_IRQ,
|
||||
WDOG_BARK_IRQ,
|
||||
AICL_FAIL_IRQ,
|
||||
AICL_DONE_IRQ,
|
||||
SMB_EN_IRQ,
|
||||
IMP_TRIGGER_IRQ,
|
||||
TEMP_CHANGE_IRQ,
|
||||
TEMP_CHANGE_SMB_IRQ,
|
||||
/* FLASH */
|
||||
VREG_OK_IRQ,
|
||||
ILIM_S2_IRQ,
|
||||
ILIM_S1_IRQ,
|
||||
VOUT_DOWN_IRQ,
|
||||
VOUT_UP_IRQ,
|
||||
FLASH_STATE_CHANGE_IRQ,
|
||||
TORCH_REQ_IRQ,
|
||||
FLASH_EN_IRQ,
|
||||
SDAM_STS_IRQ,
|
||||
/* END */
|
||||
SMB_IRQ_MAX,
|
||||
};
|
||||
|
||||
enum float_options {
|
||||
FLOAT_DCP = 1,
|
||||
FLOAT_SDP = 2,
|
||||
DISABLE_CHARGING = 3,
|
||||
SUSPEND_INPUT = 4,
|
||||
};
|
||||
|
||||
enum chg_term_config_src {
|
||||
ITERM_SRC_UNSPECIFIED,
|
||||
ITERM_SRC_ADC,
|
||||
ITERM_SRC_ANALOG
|
||||
};
|
||||
|
||||
enum comp_clamp_levels {
|
||||
CLAMP_LEVEL_DEFAULT = 0,
|
||||
CLAMP_LEVEL_1,
|
||||
MAX_CLAMP_LEVEL,
|
||||
};
|
||||
|
||||
struct clamp_config {
|
||||
u16 reg[3];
|
||||
u16 val[3];
|
||||
};
|
||||
|
||||
struct smb_irq_info {
|
||||
const char *name;
|
||||
const irq_handler_t handler;
|
||||
const bool wake;
|
||||
const struct storm_watch storm_data;
|
||||
struct smb_irq_data *irq_data;
|
||||
int irq;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static const unsigned int smblib_extcon_cable[] = {
|
||||
EXTCON_USB,
|
||||
EXTCON_USB_HOST,
|
||||
EXTCON_NONE,
|
||||
};
|
||||
|
||||
enum lpd_reason {
|
||||
LPD_NONE,
|
||||
LPD_MOISTURE_DETECTED,
|
||||
LPD_FLOATING_CABLE,
|
||||
};
|
||||
|
||||
/* Following states are applicable only for floating cable during LPD */
|
||||
enum lpd_stage {
|
||||
/* initial stage */
|
||||
LPD_STAGE_NONE,
|
||||
/* started and ongoing */
|
||||
LPD_STAGE_FLOAT,
|
||||
/* cancel if started, or don't start */
|
||||
LPD_STAGE_FLOAT_CANCEL,
|
||||
/* confirmed and mitigation measures taken for 60 s */
|
||||
LPD_STAGE_COMMIT,
|
||||
};
|
||||
|
||||
enum thermal_status_levels {
|
||||
TEMP_SHUT_DOWN = 0,
|
||||
TEMP_SHUT_DOWN_SMB,
|
||||
TEMP_ALERT_LEVEL,
|
||||
TEMP_ABOVE_RANGE,
|
||||
TEMP_WITHIN_RANGE,
|
||||
TEMP_BELOW_RANGE,
|
||||
};
|
||||
|
||||
enum icl_override_mode {
|
||||
/* APSD/Type-C/QC auto */
|
||||
HW_AUTO_MODE,
|
||||
/* 100/150/500/900mA */
|
||||
SW_OVERRIDE_USB51_MODE,
|
||||
/* ICL other than USB51 */
|
||||
SW_OVERRIDE_HC_MODE,
|
||||
};
|
||||
|
||||
/* EXTCON_USB and EXTCON_USB_HOST are mutually exclusive */
|
||||
static const u32 smblib_extcon_exclusive[] = {0x3, 0};
|
||||
|
||||
struct smb_regulator {
|
||||
struct regulator_dev *rdev;
|
||||
struct regulator_desc rdesc;
|
||||
};
|
||||
|
||||
struct smb_irq_data {
|
||||
void *parent_data;
|
||||
const char *name;
|
||||
struct storm_watch storm_data;
|
||||
};
|
||||
|
||||
struct smb_chg_param {
|
||||
const char *name;
|
||||
u16 reg;
|
||||
int min_u;
|
||||
int max_u;
|
||||
int step_u;
|
||||
int (*get_proc)(struct smb_chg_param *param,
|
||||
u8 val_raw);
|
||||
int (*set_proc)(struct smb_chg_param *param,
|
||||
int val_u,
|
||||
u8 *val_raw);
|
||||
};
|
||||
|
||||
struct buck_boost_freq {
|
||||
int freq_khz;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
struct smb_chg_freq {
|
||||
unsigned int freq_5V;
|
||||
unsigned int freq_6V_8V;
|
||||
unsigned int freq_9V;
|
||||
unsigned int freq_12V;
|
||||
unsigned int freq_removal;
|
||||
unsigned int freq_below_otg_threshold;
|
||||
unsigned int freq_above_otg_threshold;
|
||||
};
|
||||
|
||||
struct smb_params {
|
||||
struct smb_chg_param fcc;
|
||||
struct smb_chg_param fv;
|
||||
struct smb_chg_param usb_icl;
|
||||
struct smb_chg_param icl_max_stat;
|
||||
struct smb_chg_param icl_stat;
|
||||
struct smb_chg_param otg_cl;
|
||||
struct smb_chg_param dc_icl;
|
||||
struct smb_chg_param jeita_cc_comp_hot;
|
||||
struct smb_chg_param jeita_cc_comp_cold;
|
||||
struct smb_chg_param freq_switcher;
|
||||
struct smb_chg_param aicl_5v_threshold;
|
||||
struct smb_chg_param aicl_cont_threshold;
|
||||
};
|
||||
|
||||
struct parallel_params {
|
||||
struct power_supply *psy;
|
||||
};
|
||||
|
||||
struct smb_iio {
|
||||
struct iio_channel *temp_chan;
|
||||
struct iio_channel *usbin_i_chan;
|
||||
struct iio_channel *usbin_v_chan;
|
||||
struct iio_channel *mid_chan;
|
||||
struct iio_channel *batt_i_chan;
|
||||
struct iio_channel *connector_temp_chan;
|
||||
struct iio_channel *sbux_chan;
|
||||
struct iio_channel *vph_v_chan;
|
||||
struct iio_channel *die_temp_chan;
|
||||
struct iio_channel *skin_temp_chan;
|
||||
struct iio_channel *smb_temp_chan;
|
||||
};
|
||||
|
||||
struct smb_charger {
|
||||
struct device *dev;
|
||||
char *name;
|
||||
struct regmap *regmap;
|
||||
struct smb_irq_info *irq_info;
|
||||
struct smb_params param;
|
||||
struct smb_iio iio;
|
||||
int *debug_mask;
|
||||
int pd_disabled;
|
||||
enum smb_mode mode;
|
||||
struct smb_chg_freq chg_freq;
|
||||
int otg_delay_ms;
|
||||
int weak_chg_icl_ua;
|
||||
u32 sdam_base;
|
||||
bool pd_not_supported;
|
||||
|
||||
/* locks */
|
||||
struct mutex smb_lock;
|
||||
struct mutex ps_change_lock;
|
||||
struct mutex irq_status_lock;
|
||||
struct mutex dcin_aicl_lock;
|
||||
spinlock_t typec_pr_lock;
|
||||
struct mutex adc_lock;
|
||||
struct mutex dpdm_lock;
|
||||
struct mutex typec_lock;
|
||||
|
||||
/* power supplies */
|
||||
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;
|
||||
|
||||
/* parallel charging */
|
||||
struct parallel_params pl;
|
||||
|
||||
/* CC Mode */
|
||||
int adapter_cc_mode;
|
||||
int thermal_overheat;
|
||||
|
||||
/* regulators */
|
||||
struct smb_regulator *vbus_vreg;
|
||||
struct smb_regulator *vconn_vreg;
|
||||
struct regulator *dpdm_reg;
|
||||
|
||||
/* typec */
|
||||
struct typec_port *typec_port;
|
||||
struct typec_capability typec_caps;
|
||||
struct typec_partner *typec_partner;
|
||||
struct typec_partner_desc typec_partner_desc;
|
||||
|
||||
/* votables */
|
||||
struct votable *dc_suspend_votable;
|
||||
struct votable *fcc_votable;
|
||||
struct votable *fcc_main_votable;
|
||||
struct votable *fv_votable;
|
||||
struct votable *usb_icl_votable;
|
||||
struct votable *awake_votable;
|
||||
struct votable *pl_disable_votable;
|
||||
struct votable *chg_disable_votable;
|
||||
struct votable *pl_enable_votable_indirect;
|
||||
struct votable *cp_disable_votable;
|
||||
struct votable *cp_ilim_votable;
|
||||
struct votable *smb_override_votable;
|
||||
struct votable *icl_irq_disable_votable;
|
||||
struct votable *limited_irq_disable_votable;
|
||||
struct votable *hdc_irq_disable_votable;
|
||||
struct votable *temp_change_irq_disable_votable;
|
||||
struct votable *qnovo_disable_votable;
|
||||
|
||||
/* work */
|
||||
struct work_struct bms_update_work;
|
||||
struct work_struct pl_update_work;
|
||||
struct work_struct jeita_update_work;
|
||||
struct work_struct moisture_protection_work;
|
||||
struct work_struct chg_termination_work;
|
||||
struct work_struct dcin_aicl_work;
|
||||
struct work_struct cp_status_change_work;
|
||||
struct delayed_work ps_change_timeout_work;
|
||||
struct delayed_work clear_hdc_work;
|
||||
struct delayed_work icl_change_work;
|
||||
struct delayed_work pl_enable_work;
|
||||
struct delayed_work uusb_otg_work;
|
||||
struct delayed_work bb_removal_work;
|
||||
struct delayed_work lpd_ra_open_work;
|
||||
struct delayed_work lpd_detach_work;
|
||||
struct delayed_work thermal_regulation_work;
|
||||
struct delayed_work usbov_dbc_work;
|
||||
struct delayed_work pr_swap_detach_work;
|
||||
struct delayed_work pr_lock_clear_work;
|
||||
struct delayed_work role_reversal_check;
|
||||
|
||||
struct alarm lpd_recheck_timer;
|
||||
struct alarm moisture_protection_alarm;
|
||||
struct alarm chg_termination_alarm;
|
||||
struct alarm dcin_aicl_alarm;
|
||||
|
||||
struct timer_list apsd_timer;
|
||||
|
||||
struct charger_param chg_param;
|
||||
/* secondary charger config */
|
||||
bool sec_pl_present;
|
||||
bool sec_cp_present;
|
||||
int sec_chg_selected;
|
||||
int cp_reason;
|
||||
int cp_topo;
|
||||
|
||||
/* pd */
|
||||
int voltage_min_uv;
|
||||
int voltage_max_uv;
|
||||
int pd_active;
|
||||
bool pd_hard_reset;
|
||||
bool pr_lock_in_progress;
|
||||
bool pr_swap_in_progress;
|
||||
bool early_usb_attach;
|
||||
bool ok_to_pd;
|
||||
bool typec_legacy;
|
||||
bool typec_irq_en;
|
||||
bool typec_role_swap_failed;
|
||||
|
||||
/* cached status */
|
||||
bool system_suspend_supported;
|
||||
int boost_threshold_ua;
|
||||
int system_temp_level;
|
||||
int thermal_levels;
|
||||
int *thermal_mitigation;
|
||||
int dcp_icl_ua;
|
||||
int fake_capacity;
|
||||
int fake_batt_status;
|
||||
bool step_chg_enabled;
|
||||
bool sw_jeita_enabled;
|
||||
bool typec_legacy_use_rp_icl;
|
||||
bool is_hdc;
|
||||
bool chg_done;
|
||||
int connector_type;
|
||||
bool otg_en;
|
||||
bool suspend_input_on_debug_batt;
|
||||
bool fake_chg_status_on_debug_batt;
|
||||
int default_icl_ua;
|
||||
int otg_cl_ua;
|
||||
bool uusb_apsd_rerun_done;
|
||||
bool typec_present;
|
||||
int fake_input_current_limited;
|
||||
int typec_mode;
|
||||
int dr_mode;
|
||||
int usb_icl_change_irq_enabled;
|
||||
u32 jeita_status;
|
||||
u8 float_cfg;
|
||||
bool jeita_arb_flag;
|
||||
bool use_extcon;
|
||||
bool otg_present;
|
||||
bool hvdcp_disable;
|
||||
int hw_max_icl_ua;
|
||||
int auto_recharge_soc;
|
||||
enum sink_src_mode sink_src_mode;
|
||||
enum power_supply_typec_power_role power_role;
|
||||
enum jeita_cfg_stat jeita_configured;
|
||||
int charger_temp_max;
|
||||
int smb_temp_max;
|
||||
u8 typec_try_mode;
|
||||
enum lpd_stage lpd_stage;
|
||||
bool lpd_disabled;
|
||||
enum lpd_reason lpd_reason;
|
||||
bool fcc_stepper_enable;
|
||||
int die_temp;
|
||||
int smb_temp;
|
||||
int skin_temp;
|
||||
int connector_temp;
|
||||
int thermal_status;
|
||||
int main_fcc_max;
|
||||
u32 jeita_soft_thlds[2];
|
||||
u32 jeita_soft_hys_thlds[2];
|
||||
int jeita_soft_fcc[2];
|
||||
int jeita_soft_fv[2];
|
||||
bool moisture_present;
|
||||
bool uusb_moisture_protection_capable;
|
||||
bool uusb_moisture_protection_enabled;
|
||||
bool hw_die_temp_mitigation;
|
||||
bool hw_connector_mitigation;
|
||||
bool hw_skin_temp_mitigation;
|
||||
bool en_skin_therm_mitigation;
|
||||
int connector_pull_up;
|
||||
int smb_pull_up;
|
||||
int aicl_5v_threshold_mv;
|
||||
int default_aicl_5v_threshold_mv;
|
||||
int aicl_cont_threshold_mv;
|
||||
int default_aicl_cont_threshold_mv;
|
||||
bool aicl_max_reached;
|
||||
int charge_full_cc;
|
||||
int cc_soc_ref;
|
||||
int last_cc_soc;
|
||||
int term_vbat_uv;
|
||||
int usbin_forced_max_uv;
|
||||
int init_thermal_ua;
|
||||
u32 comp_clamp_level;
|
||||
int wls_icl_ua;
|
||||
int cutoff_count;
|
||||
bool dcin_aicl_done;
|
||||
bool hvdcp3_standalone_config;
|
||||
bool dcin_icl_user_set;
|
||||
bool dpdm_enabled;
|
||||
bool apsd_ext_timeout;
|
||||
bool qc3p5_detected;
|
||||
|
||||
/* workaround flag */
|
||||
u32 wa_flags;
|
||||
int boost_current_ua;
|
||||
int qc2_max_pulses;
|
||||
enum qc2_non_comp_voltage qc2_unsupported_voltage;
|
||||
bool dbc_usbov;
|
||||
|
||||
/* extcon for VBUS / ID notification to USB for uUSB */
|
||||
struct extcon_dev *extcon;
|
||||
|
||||
/* battery profile */
|
||||
int batt_profile_fcc_ua;
|
||||
int batt_profile_fv_uv;
|
||||
|
||||
int usb_icl_delta_ua;
|
||||
int pulse_cnt;
|
||||
|
||||
int die_health;
|
||||
int connector_health;
|
||||
|
||||
/* flash */
|
||||
u32 flash_derating_soc;
|
||||
u32 flash_disable_soc;
|
||||
u32 headroom_mode;
|
||||
bool flash_init_done;
|
||||
bool flash_active;
|
||||
u32 irq_status;
|
||||
|
||||
/* wireless */
|
||||
int dcin_uv_count;
|
||||
ktime_t dcin_uv_last_time;
|
||||
int last_wls_vout;
|
||||
};
|
||||
|
||||
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val);
|
||||
int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val);
|
||||
int smblib_write(struct smb_charger *chg, u16 addr, u8 val);
|
||||
int smblib_batch_write(struct smb_charger *chg, u16 addr, u8 *val, int count);
|
||||
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);
|
||||
int smblib_vbus_regulator_disable(struct regulator_dev *rdev);
|
||||
int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev);
|
||||
|
||||
int smblib_vconn_regulator_enable(struct regulator_dev *rdev);
|
||||
int smblib_vconn_regulator_disable(struct regulator_dev *rdev);
|
||||
int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev);
|
||||
|
||||
irqreturn_t default_irq_handler(int irq, void *data);
|
||||
irqreturn_t smb_en_irq_handler(int irq, void *data);
|
||||
irqreturn_t chg_state_change_irq_handler(int irq, void *data);
|
||||
irqreturn_t batt_temp_changed_irq_handler(int irq, void *data);
|
||||
irqreturn_t batt_psy_changed_irq_handler(int irq, void *data);
|
||||
irqreturn_t usbin_uv_irq_handler(int irq, void *data);
|
||||
irqreturn_t usb_plugin_irq_handler(int irq, void *data);
|
||||
irqreturn_t usb_source_change_irq_handler(int irq, void *data);
|
||||
irqreturn_t icl_change_irq_handler(int irq, void *data);
|
||||
irqreturn_t typec_state_change_irq_handler(int irq, void *data);
|
||||
irqreturn_t typec_attach_detach_irq_handler(int irq, void *data);
|
||||
irqreturn_t dcin_uv_irq_handler(int irq, void *data);
|
||||
irqreturn_t dc_plugin_irq_handler(int irq, void *data);
|
||||
irqreturn_t high_duty_cycle_irq_handler(int irq, void *data);
|
||||
irqreturn_t switcher_power_ok_irq_handler(int irq, void *data);
|
||||
irqreturn_t wdog_snarl_irq_handler(int irq, void *data);
|
||||
irqreturn_t wdog_bark_irq_handler(int irq, void *data);
|
||||
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,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_batt_present(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_batt_capacity(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_batt_status(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
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 smblib_get_batt_current_now(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_batt_health(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_system_temp_level(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
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 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_batt_capacity(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_batt_status(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
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 smblib_get_prop_dc_present(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_dc_online(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
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);
|
||||
int smblib_get_prop_usb_online(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_usb_online(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_usb_suspend(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
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 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,
|
||||
union power_supply_propval *val);
|
||||
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 smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
|
||||
union power_supply_propval *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 smblib_get_prop_typec_power_role(struct smb_charger *chg,
|
||||
union power_supply_propval *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 smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_pe_start(struct smb_charger *chg,
|
||||
union power_supply_propval *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 smblib_get_die_health(struct smb_charger *chg,
|
||||
union power_supply_propval *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 smblib_set_prop_pd_current_max(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_sdp_current_max(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_pd_voltage_max(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_pd_voltage_min(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_typec_power_role(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_typec_select_rp(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_pd_active(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_ship_mode(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_rechg_soc_thresh(struct smb_charger *chg,
|
||||
const union power_supply_propval *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 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);
|
||||
int smblib_run_aicl(struct smb_charger *chg, int type);
|
||||
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 smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
|
||||
const union power_supply_propval *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 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,
|
||||
ktime_t time);
|
||||
int smblib_toggle_smb_en(struct smb_charger *chg, int toggle);
|
||||
void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable);
|
||||
void smblib_hvdcp_hw_inov_enable(struct smb_charger *chg, bool enable);
|
||||
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 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);
|
||||
#endif /* __SMB5_CHARGER_H */
|
||||
557
drivers/power/supply/qcom/smb5-reg.h
Normal file
557
drivers/power/supply/qcom/smb5-reg.h
Normal file
|
|
@ -0,0 +1,557 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SMB5_CHARGER_REG_H
|
||||
#define __SMB5_CHARGER_REG_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define CHGR_BASE 0x1000
|
||||
#define DCDC_BASE 0x1100
|
||||
#define BATIF_BASE 0x1200
|
||||
#define USBIN_BASE 0x1300
|
||||
#define DCIN_BASE 0x1400
|
||||
#define TYPEC_BASE 0X1500
|
||||
#define MISC_BASE 0x1600
|
||||
#define MISC_PBS_BASE 0x7500
|
||||
|
||||
#define PERPH_TYPE_OFFSET 0x04
|
||||
#define TYPE_MASK GENMASK(7, 0)
|
||||
#define PERPH_SUBTYPE_OFFSET 0x05
|
||||
#define SUBTYPE_MASK GENMASK(7, 0)
|
||||
#define INT_RT_STS_OFFSET 0x10
|
||||
#define SDAM_TYPE 0x2E
|
||||
|
||||
/********************************
|
||||
* CHGR Peripheral Registers *
|
||||
********************************/
|
||||
#define BATTERY_CHARGER_STATUS_1_REG (CHGR_BASE + 0x06)
|
||||
#define BATTERY_CHARGER_STATUS_MASK GENMASK(2, 0)
|
||||
enum {
|
||||
INHIBIT_CHARGE = 0,
|
||||
TRICKLE_CHARGE,
|
||||
PRE_CHARGE,
|
||||
FULLON_CHARGE,
|
||||
TAPER_CHARGE,
|
||||
TERMINATE_CHARGE,
|
||||
PAUSE_CHARGE,
|
||||
DISABLE_CHARGE,
|
||||
};
|
||||
|
||||
#define BATTERY_CHARGER_STATUS_2_REG (CHGR_BASE + 0x07)
|
||||
#define CHARGER_ERROR_STATUS_BAT_OV_BIT BIT(1)
|
||||
|
||||
#define BATTERY_CHARGER_STATUS_5_REG (CHGR_BASE + 0x0B)
|
||||
#define ENABLE_TRICKLE_BIT BIT(2)
|
||||
#define ENABLE_PRE_CHARGING_BIT BIT(1)
|
||||
#define ENABLE_FULLON_MODE_BIT BIT(0)
|
||||
|
||||
#define BATTERY_CHARGER_STATUS_7_REG (CHGR_BASE + 0x0D)
|
||||
#define BAT_TEMP_STATUS_SOFT_LIMIT_MASK GENMASK(5, 4)
|
||||
#define BAT_TEMP_STATUS_HOT_SOFT_BIT BIT(5)
|
||||
#define BAT_TEMP_STATUS_COLD_SOFT_BIT BIT(4)
|
||||
#define BAT_TEMP_STATUS_HARD_LIMIT_MASK GENMASK(3, 2)
|
||||
#define BAT_TEMP_STATUS_TOO_HOT_BIT BIT(3)
|
||||
#define BAT_TEMP_STATUS_TOO_COLD_BIT BIT(2)
|
||||
#define BAT_TEMP_STATUS_TOO_HOT_AFP_BIT BIT(1)
|
||||
#define BAT_TEMP_STATUS_TOO_COLD_AFP_BIT BIT(0)
|
||||
|
||||
#define CHARGING_ENABLE_CMD_REG (CHGR_BASE + 0x42)
|
||||
#define CHARGING_ENABLE_CMD_BIT BIT(0)
|
||||
|
||||
#define CHARGING_PAUSE_CMD_REG (CHGR_BASE + 0x43)
|
||||
#define CHARGING_PAUSE_CMD_BIT BIT(0)
|
||||
|
||||
#define CHGR_CFG2_REG (CHGR_BASE + 0x51)
|
||||
#define RECHG_MASK GENMASK(2, 1)
|
||||
#define VBAT_BASED_RECHG_BIT BIT(2)
|
||||
#define SOC_BASED_RECHG_BIT GENMASK(2, 1)
|
||||
#define CHARGER_INHIBIT_BIT BIT(0)
|
||||
|
||||
#define CHGR_FAST_CHARGE_CURRENT_CFG_REG (CHGR_BASE + 0x61)
|
||||
|
||||
#define CHGR_ADC_ITERM_UP_THD_MSB_REG (CHGR_BASE + 0x67)
|
||||
#define CHGR_ADC_ITERM_UP_THD_LSB_REG (CHGR_BASE + 0x68)
|
||||
#define CHGR_ADC_ITERM_LO_THD_MSB_REG (CHGR_BASE + 0x69)
|
||||
#define CHGR_ADC_ITERM_LO_THD_LSB_REG (CHGR_BASE + 0x6A)
|
||||
|
||||
#define CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG (CHGR_BASE + 0x6B)
|
||||
#define NO_OF_SAMPLE_FOR_RCHG_SHIFT 2
|
||||
#define NO_OF_SAMPLE_FOR_RCHG GENMASK(3, 2)
|
||||
|
||||
#define CHGR_ADC_TERM_CFG_REG (CHGR_BASE + 0x6C)
|
||||
#define TERM_BASED_ON_SYNC_CONV_OR_SAMPLE_CNT BIT(0)
|
||||
#define TERM_BASED_ON_SYNC_CONV 0
|
||||
#define TERM_BASED_ON_SAMPLE_CNT 1
|
||||
|
||||
#define CHGR_FLOAT_VOLTAGE_CFG_REG (CHGR_BASE + 0x70)
|
||||
|
||||
#define CHARGE_INHIBIT_THRESHOLD_CFG_REG (CHGR_BASE + 0x72)
|
||||
#define CHARGE_INHIBIT_THRESHOLD_MASK GENMASK(1, 0)
|
||||
#define INHIBIT_ANALOG_VFLT_MINUS_50MV 0
|
||||
#define INHIBIT_ANALOG_VFLT_MINUS_100MV 1
|
||||
#define INHIBIT_ANALOG_VFLT_MINUS_200MV 2
|
||||
#define INHIBIT_ANALOG_VFLT_MINUS_300MV 3
|
||||
|
||||
#define CHARGE_RCHG_SOC_THRESHOLD_CFG_REG (CHGR_BASE + 0x7D)
|
||||
|
||||
#define CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG (CHGR_BASE + 0x7E)
|
||||
|
||||
#define CHGR_ADC_RECHARGE_THRESHOLD_LSB_REG (CHGR_BASE + 0x7F)
|
||||
|
||||
#define JEITA_EN_CFG_REG (CHGR_BASE + 0x90)
|
||||
#define JEITA_EN_HOT_SL_FCV_BIT BIT(3)
|
||||
#define JEITA_EN_COLD_SL_FCV_BIT BIT(2)
|
||||
#define JEITA_EN_HOT_SL_CCC_BIT BIT(1)
|
||||
#define JEITA_EN_COLD_SL_CCC_BIT BIT(0)
|
||||
|
||||
#define JEITA_CCCOMP_CFG_HOT_REG (CHGR_BASE + 0x92)
|
||||
#define JEITA_CCCOMP_CFG_COLD_REG (CHGR_BASE + 0x93)
|
||||
|
||||
#define CHGR_JEITA_THRESHOLD_BASE_REG(i) (CHGR_BASE + 0x94 + (i * 4))
|
||||
#define CHGR_JEITA_HOT_THRESHOLD_MSB_REG CHGR_JEITA_THRESHOLD_BASE_REG(0)
|
||||
|
||||
#define CHGR_FAST_CHARGE_SAFETY_TIMER_CFG_REG (CHGR_BASE + 0xA2)
|
||||
#define FAST_CHARGE_SAFETY_TIMER_192_MIN 0x0
|
||||
#define FAST_CHARGE_SAFETY_TIMER_384_MIN 0x1
|
||||
#define FAST_CHARGE_SAFETY_TIMER_768_MIN 0x2
|
||||
#define FAST_CHARGE_SAFETY_TIMER_1536_MIN 0x3
|
||||
|
||||
#define CHGR_ENG_CHARGING_CFG_REG (CHGR_BASE + 0xC0)
|
||||
#define CHGR_ITERM_USE_ANALOG_BIT BIT(3)
|
||||
|
||||
/********************************
|
||||
* DCDC Peripheral Registers *
|
||||
********************************/
|
||||
#define ICL_MAX_STATUS_REG (DCDC_BASE + 0x06)
|
||||
#define ICL_STATUS_REG (DCDC_BASE + 0x07)
|
||||
#define AICL_ICL_STATUS_REG (DCDC_BASE + 0x08)
|
||||
|
||||
#define AICL_STATUS_REG (DCDC_BASE + 0x0A)
|
||||
#define SOFT_ILIMIT_BIT BIT(6)
|
||||
#define AICL_DONE_BIT BIT(0)
|
||||
|
||||
#define POWER_PATH_STATUS_REG (DCDC_BASE + 0x0B)
|
||||
#define USBIN_SUSPEND_STS_BIT BIT(6)
|
||||
#define USE_USBIN_BIT BIT(4)
|
||||
#define USE_DCIN_BIT BIT(3)
|
||||
#define POWER_PATH_MASK GENMASK(2, 1)
|
||||
#define VALID_INPUT_POWER_SOURCE_STS_BIT BIT(0)
|
||||
|
||||
#define DCDC_CMD_OTG_REG (DCDC_BASE + 0x40)
|
||||
#define OTG_EN_BIT BIT(0)
|
||||
|
||||
#define DCDC_FSW_SEL_REG (DCDC_BASE + 0x50)
|
||||
|
||||
#define DCDC_OTG_CURRENT_LIMIT_CFG_REG (DCDC_BASE + 0x52)
|
||||
|
||||
#define DCDC_OTG_CFG_REG (DCDC_BASE + 0x53)
|
||||
#define OTG_EN_SRC_CFG_BIT BIT(1)
|
||||
|
||||
#define OTG_FAULT_CONDITION_CFG_REG (DCDC_BASE + 0x56)
|
||||
#define USBIN_MID_COMP_FAULT_EN_BIT BIT(5)
|
||||
#define USBIN_COLLAPSE_FAULT_EN_BIT BIT(4)
|
||||
|
||||
#define DCDC_CFG_REF_MAX_PSNS_REG (DCDC_BASE + 0x8C)
|
||||
|
||||
#define DCDC_ENG_SDCDC_CFG5_REG (DCDC_BASE + 0xC4)
|
||||
#define ENG_SDCDC_BAT_HPWR_MASK GENMASK(7, 6)
|
||||
enum {
|
||||
BOOST_MODE_THRESH_3P3_V,
|
||||
BOOST_MODE_THRESH_3P4_V = 0x40,
|
||||
BOOST_MODE_THRESH_3P5_V = 0x80,
|
||||
BOOST_MODE_THRESH_3P6_V = 0xC0
|
||||
};
|
||||
|
||||
/********************************
|
||||
* BATIF Peripheral Registers *
|
||||
********************************/
|
||||
|
||||
/* BATIF Interrupt Bits */
|
||||
#define VPH_OV_RT_STS_BIT BIT(7)
|
||||
#define BUCK_OC_RT_STS_BIT BIT(6)
|
||||
#define BAT_TERMINAL_MISSING_RT_STS_BIT BIT(5)
|
||||
#define BAT_THERM_OR_ID_MISSING_RT_STS_BIT BIT(4)
|
||||
#define BAT_LOW_RT_STS_BIT BIT(3)
|
||||
#define BAT_OV_RT_STS_BIT BIT(2)
|
||||
#define ALL_CHNL_CONV_DONE_RT_STS BIT(1)
|
||||
#define BAT_TEMP_RT_STS_BIT BIT(0)
|
||||
|
||||
#define SHIP_MODE_REG (BATIF_BASE + 0x40)
|
||||
#define SHIP_MODE_EN_BIT BIT(0)
|
||||
|
||||
#define BATIF_ADC_CHANNEL_EN_REG (BATIF_BASE + 0x82)
|
||||
#define IBATT_CHANNEL_EN_BIT BIT(6)
|
||||
#define CONN_THM_CHANNEL_EN_BIT BIT(4)
|
||||
#define DIE_TEMP_CHANNEL_EN_BIT BIT(2)
|
||||
#define MISC_THM_CHANNEL_EN_BIT BIT(1)
|
||||
|
||||
#define BATIF_ADC_INTERNAL_PULL_UP_REG (BATIF_BASE + 0x86)
|
||||
#define INTERNAL_PULL_UP_CONN_THM_MASK GENMASK(5, 4)
|
||||
#define CONN_THM_SHIFT 4
|
||||
#define INTERNAL_PULL_NO_PULL 0x00
|
||||
#define INTERNAL_PULL_30K_PULL 0x01
|
||||
#define INTERNAL_PULL_100K_PULL 0x02
|
||||
#define INTERNAL_PULL_400K_PULL 0x03
|
||||
|
||||
/********************************
|
||||
* USBIN Peripheral Registers *
|
||||
********************************/
|
||||
#define APSD_STATUS_REG (USBIN_BASE + 0x07)
|
||||
#define APSD_STATUS_7_BIT BIT(7)
|
||||
#define HVDCP_CHECK_TIMEOUT_BIT BIT(6)
|
||||
#define SLOW_PLUGIN_TIMEOUT_BIT BIT(5)
|
||||
#define ENUMERATION_DONE_BIT BIT(4)
|
||||
#define VADP_CHANGE_DONE_AFTER_AUTH_BIT BIT(3)
|
||||
#define QC_AUTH_DONE_STATUS_BIT BIT(2)
|
||||
#define QC_CHARGER_BIT BIT(1)
|
||||
#define APSD_DTC_STATUS_DONE_BIT BIT(0)
|
||||
|
||||
#define APSD_RESULT_STATUS_REG (USBIN_BASE + 0x08)
|
||||
#define APSD_RESULT_STATUS_7_BIT BIT(7)
|
||||
#define APSD_RESULT_STATUS_MASK GENMASK(6, 0)
|
||||
#define QC_3P0_BIT BIT(6)
|
||||
#define QC_2P0_BIT BIT(5)
|
||||
#define FLOAT_CHARGER_BIT BIT(4)
|
||||
#define DCP_CHARGER_BIT BIT(3)
|
||||
#define CDP_CHARGER_BIT BIT(2)
|
||||
#define OCP_CHARGER_BIT BIT(1)
|
||||
#define SDP_CHARGER_BIT BIT(0)
|
||||
|
||||
#define QC_CHANGE_STATUS_REG (USBIN_BASE + 0x09)
|
||||
#define QC_12V_BIT BIT(2)
|
||||
#define QC_9V_BIT BIT(1)
|
||||
#define QC_5V_BIT BIT(0)
|
||||
#define QC_2P0_STATUS_MASK GENMASK(2, 0)
|
||||
|
||||
/* USBIN Interrupt Bits */
|
||||
#define USBIN_ICL_CHANGE_RT_STS_BIT BIT(7)
|
||||
#define USBIN_SOURCE_CHANGE_RT_STS_BIT BIT(6)
|
||||
#define USBIN_REVI_RT_STS_BIT BIT(5)
|
||||
#define USBIN_PLUGIN_RT_STS_BIT BIT(4)
|
||||
#define USBIN_OV_RT_STS_BIT BIT(3)
|
||||
#define USBIN_UV_RT_STS_BIT BIT(2)
|
||||
#define USBIN_VASHDN_RT_STS_BIT BIT(1)
|
||||
#define USBIN_COLLAPSE_RT_STS_BIT BIT(0)
|
||||
|
||||
#define USBIN_CMD_IL_REG (USBIN_BASE + 0x40)
|
||||
#define USBIN_SUSPEND_BIT BIT(0)
|
||||
|
||||
#define CMD_APSD_REG (USBIN_BASE + 0x41)
|
||||
#define APSD_RERUN_BIT BIT(0)
|
||||
|
||||
#define CMD_ICL_OVERRIDE_REG (USBIN_BASE + 0x42)
|
||||
#define ICL_OVERRIDE_BIT BIT(0)
|
||||
|
||||
#define CMD_HVDCP_2_REG (USBIN_BASE + 0x43)
|
||||
#define FORCE_12V_BIT BIT(5)
|
||||
#define FORCE_9V_BIT BIT(4)
|
||||
#define FORCE_5V_BIT BIT(3)
|
||||
#define IDLE_BIT BIT(2)
|
||||
#define SINGLE_DECREMENT_BIT BIT(1)
|
||||
#define SINGLE_INCREMENT_BIT BIT(0)
|
||||
|
||||
#define USBIN_ADAPTER_ALLOW_OVERRIDE_REG (USBIN_BASE + 0x44)
|
||||
#define CONTINUOUS BIT(3)
|
||||
#define FORCE_12V BIT(2)
|
||||
#define FORCE_9V BIT(1)
|
||||
#define FORCE_5V BIT(0)
|
||||
#define FORCE_NULL 0
|
||||
|
||||
#define USB_CMD_PULLDOWN_REG (USBIN_BASE + 0x45)
|
||||
#define EN_PULLDOWN_USB_IN_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_CFG_REG (USBIN_BASE + 0x58)
|
||||
#define BC1P2_START_ON_CC_BIT BIT(7)
|
||||
|
||||
#define HVDCP_PULSE_COUNT_MAX_REG (USBIN_BASE + 0x5B)
|
||||
#define HVDCP_PULSE_COUNT_MAX_QC2_MASK GENMASK(7, 6)
|
||||
enum {
|
||||
HVDCP_PULSE_COUNT_MAX_QC2_5V = 0,
|
||||
HVDCP_PULSE_COUNT_MAX_QC2_9V = 0x40,
|
||||
HVDCP_PULSE_COUNT_MAX_QC2_12V = 0x80,
|
||||
HVDCP_PULSE_COUNT_MAX_QC2_INVALID = 0xC0
|
||||
};
|
||||
|
||||
#define USBIN_OPTIONS_1_CFG_REG (USBIN_BASE + 0x62)
|
||||
#define HVDCP_AUTH_ALG_EN_CFG_BIT BIT(6)
|
||||
#define HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT BIT(5)
|
||||
#define BC1P2_SRC_DETECT_BIT BIT(3)
|
||||
#define HVDCP_EN_BIT BIT(2)
|
||||
|
||||
#define USBIN_OPTIONS_2_CFG_REG (USBIN_BASE + 0x63)
|
||||
#define DCD_TIMEOUT_SEL_BIT BIT(5)
|
||||
#define FLOAT_OPTIONS_MASK GENMASK(2, 0)
|
||||
#define FLOAT_DIS_CHGING_CFG_BIT BIT(2)
|
||||
#define SUSPEND_FLOAT_CFG_BIT BIT(1)
|
||||
#define FORCE_FLOAT_SDP_CFG_BIT BIT(0)
|
||||
|
||||
#define USBIN_LOAD_CFG_REG (USBIN_BASE + 0x65)
|
||||
#define ICL_OVERRIDE_AFTER_APSD_BIT BIT(4)
|
||||
#define USBIN_AICL_STEP_TIMING_SEL_MASK GENMASK(3, 2)
|
||||
#define USBIN_IN_COLLAPSE_GF_SEL_MASK GENMASK(1, 0)
|
||||
|
||||
#define USBIN_ICL_OPTIONS_REG (USBIN_BASE + 0x66)
|
||||
#define CFG_USB3P0_SEL_BIT BIT(2)
|
||||
#define USB51_MODE_BIT BIT(1)
|
||||
#define USBIN_MODE_CHG_BIT BIT(0)
|
||||
|
||||
#define USBIN_CURRENT_LIMIT_CFG_REG (USBIN_BASE + 0x70)
|
||||
|
||||
#define USBIN_AICL_OPTIONS_CFG_REG (USBIN_BASE + 0x80)
|
||||
#define SUSPEND_ON_COLLAPSE_USBIN_BIT BIT(7)
|
||||
#define USBIN_AICL_PERIODIC_RERUN_EN_BIT BIT(4)
|
||||
#define USBIN_AICL_ADC_EN_BIT BIT(3)
|
||||
#define USBIN_AICL_EN_BIT BIT(2)
|
||||
|
||||
#define USB_ENG_SSUPPLY_USB2_REG (USBIN_BASE + 0xC0)
|
||||
#define ENG_SSUPPLY_12V_OV_OPT_BIT BIT(1)
|
||||
|
||||
#define USBIN_5V_AICL_THRESHOLD_REG (USBIN_BASE + 0x81)
|
||||
#define USBIN_CONT_AICL_THRESHOLD_REG (USBIN_BASE + 0x84)
|
||||
/********************************
|
||||
* DCIN Peripheral Registers *
|
||||
********************************/
|
||||
|
||||
/* DCIN Interrupt Bits */
|
||||
#define DCIN_PLUGIN_RT_STS_BIT BIT(4)
|
||||
|
||||
#define DCIN_CMD_IL_REG (DCIN_BASE + 0x40)
|
||||
#define DCIN_SUSPEND_BIT BIT(0)
|
||||
#define DCIN_EN_OVERRIDE_BIT BIT(1)
|
||||
#define DCIN_EN_MASK GENMASK(2, 1)
|
||||
|
||||
#define DCIN_CMD_PON_REG (DCIN_BASE + 0x45)
|
||||
#define DCIN_PON_BIT BIT(0)
|
||||
#define MID_CHG_BIT BIT(1)
|
||||
|
||||
#define DCIN_LOAD_CFG_REG (DCIN_BASE + 0x65)
|
||||
#define INPUT_MISS_POLL_EN_BIT BIT(5)
|
||||
|
||||
/********************************
|
||||
* TYPEC Peripheral Registers *
|
||||
********************************/
|
||||
#define TYPE_C_SNK_STATUS_REG (TYPEC_BASE + 0x06)
|
||||
#define DETECTED_SRC_TYPE_MASK GENMASK(6, 0)
|
||||
#define SNK_DAM_500MA_BIT BIT(6)
|
||||
#define SNK_DAM_1500MA_BIT BIT(5)
|
||||
#define SNK_DAM_3000MA_BIT BIT(4)
|
||||
#define SNK_RP_STD_BIT BIT(3)
|
||||
#define SNK_RP_1P5_BIT BIT(2)
|
||||
#define SNK_RP_3P0_BIT BIT(1)
|
||||
#define SNK_RP_SHORT_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_SRC_STATUS_REG (TYPEC_BASE + 0x08)
|
||||
#define DETECTED_SNK_TYPE_MASK GENMASK(4, 0)
|
||||
#define SRC_HIGH_BATT_BIT BIT(5)
|
||||
#define SRC_DEBUG_ACCESS_BIT BIT(4)
|
||||
#define SRC_RD_OPEN_BIT BIT(3)
|
||||
#define SRC_RD_RA_VCONN_BIT BIT(2)
|
||||
#define SRC_RA_OPEN_BIT BIT(1)
|
||||
#define AUDIO_ACCESS_RA_RA_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_STATE_MACHINE_STATUS_REG (TYPEC_BASE + 0x09)
|
||||
#define TYPEC_ATTACH_DETACH_STATE_BIT BIT(5)
|
||||
|
||||
#define TYPE_C_MISC_STATUS_REG (TYPEC_BASE + 0x0B)
|
||||
#define TYPEC_WATER_DETECTION_STATUS_BIT BIT(7)
|
||||
#define SNK_SRC_MODE_BIT BIT(6)
|
||||
#define TYPEC_VBUS_ERROR_STATUS_BIT BIT(4)
|
||||
#define TYPEC_TCCDEBOUNCE_DONE_STATUS_BIT BIT(3)
|
||||
#define CC_ORIENTATION_BIT BIT(1)
|
||||
#define CC_ATTACHED_BIT BIT(0)
|
||||
|
||||
#define LEGACY_CABLE_STATUS_REG (TYPEC_BASE + 0x0D)
|
||||
#define TYPEC_LEGACY_CABLE_STATUS_BIT BIT(1)
|
||||
#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT BIT(0)
|
||||
|
||||
#define TYPEC_U_USB_STATUS_REG (TYPEC_BASE + 0x0F)
|
||||
#define U_USB_GROUND_NOVBUS_BIT BIT(6)
|
||||
#define U_USB_GROUND_BIT BIT(4)
|
||||
#define U_USB_FMB1_BIT BIT(3)
|
||||
#define U_USB_FLOAT1_BIT BIT(2)
|
||||
#define U_USB_FMB2_BIT BIT(1)
|
||||
#define U_USB_FLOAT2_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_MODE_CFG_REG (TYPEC_BASE + 0x44)
|
||||
#define TYPEC_TRY_MODE_MASK GENMASK(4, 3)
|
||||
#define EN_TRY_SNK_BIT BIT(4)
|
||||
#define EN_TRY_SRC_BIT BIT(3)
|
||||
#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0)
|
||||
#define EN_SRC_ONLY_BIT BIT(2)
|
||||
#define EN_SNK_ONLY_BIT BIT(1)
|
||||
#define TYPEC_DISABLE_CMD_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_VCONN_CONTROL_REG (TYPEC_BASE + 0x46)
|
||||
#define VCONN_EN_ORIENTATION_BIT BIT(2)
|
||||
#define VCONN_EN_VALUE_BIT BIT(1)
|
||||
#define VCONN_EN_SRC_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_CCOUT_CONTROL_REG (TYPEC_BASE + 0x48)
|
||||
#define TYPEC_CCOUT_BUFFER_EN_BIT BIT(2)
|
||||
#define TYPEC_CCOUT_VALUE_BIT BIT(1)
|
||||
#define TYPEC_CCOUT_SRC_BIT BIT(0)
|
||||
|
||||
#define DEBUG_ACCESS_SRC_CFG_REG (TYPEC_BASE + 0x4C)
|
||||
#define EN_UNORIENTED_DEBUG_ACCESS_SRC_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_CRUDE_SENSOR_CFG_REG (TYPEC_BASE + 0x4e)
|
||||
#define EN_SRC_CRUDE_SENSOR_BIT BIT(1)
|
||||
#define EN_SNK_CRUDE_SENSOR_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_EXIT_STATE_CFG_REG (TYPEC_BASE + 0x50)
|
||||
#define BYPASS_VSAFE0V_DURING_ROLE_SWAP_BIT BIT(3)
|
||||
#define SEL_SRC_UPPER_REF_BIT BIT(2)
|
||||
#define EXIT_SNK_BASED_ON_CC_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_CURRSRC_CFG_REG (TYPEC_BASE + 0x52)
|
||||
#define TYPEC_SRC_RP_SEL_MASK GENMASK(1, 0)
|
||||
enum {
|
||||
TYPEC_SRC_RP_STD,
|
||||
TYPEC_SRC_RP_1P5A,
|
||||
TYPEC_SRC_RP_3A,
|
||||
TYPEC_SRC_RP_3A_DUPLICATE,
|
||||
TYPEC_SRC_RP_MAX_ELEMENTS
|
||||
};
|
||||
|
||||
#define TYPE_C_INTERRUPT_EN_CFG_1_REG (TYPEC_BASE + 0x5E)
|
||||
#define TYPEC_LEGACY_CABLE_INT_EN_BIT BIT(7)
|
||||
#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_BIT BIT(6)
|
||||
#define TYPEC_TRYSOURCE_DETECT_INT_EN_BIT BIT(5)
|
||||
#define TYPEC_TRYSINK_DETECT_INT_EN_BIT BIT(4)
|
||||
#define TYPEC_CCOUT_DETACH_INT_EN_BIT BIT(3)
|
||||
#define TYPEC_CCOUT_ATTACH_INT_EN_BIT BIT(2)
|
||||
#define TYPEC_VBUS_DEASSERT_INT_EN_BIT BIT(1)
|
||||
#define TYPEC_VBUS_ASSERT_INT_EN_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_INTERRUPT_EN_CFG_2_REG (TYPEC_BASE + 0x60)
|
||||
#define TYPEC_SRC_BATT_HPWR_INT_EN_BIT BIT(6)
|
||||
#define MICRO_USB_STATE_CHANGE_INT_EN_BIT BIT(5)
|
||||
#define TYPEC_STATE_MACHINE_CHANGE_INT_EN_BIT BIT(4)
|
||||
#define TYPEC_DEBUG_ACCESS_DETECT_INT_EN_BIT BIT(3)
|
||||
#define TYPEC_WATER_DETECTION_INT_EN_BIT BIT(2)
|
||||
#define TYPEC_VBUS_ERROR_INT_EN_BIT BIT(1)
|
||||
#define TYPEC_DEBOUNCE_DONE_INT_EN_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_DEBOUNCE_OPTION_REG (TYPEC_BASE + 0x62)
|
||||
#define REDUCE_TCCDEBOUNCE_TO_2MS_BIT BIT(2)
|
||||
|
||||
#define TYPE_C_SBU_CFG_REG (TYPEC_BASE + 0x6A)
|
||||
#define SEL_SBU1_ISRC_VAL 0x04
|
||||
#define SEL_SBU2_ISRC_VAL 0x01
|
||||
|
||||
#define TYPEC_U_USB_CFG_REG (TYPEC_BASE + 0x70)
|
||||
#define EN_MICRO_USB_FACTORY_MODE_BIT BIT(1)
|
||||
#define EN_MICRO_USB_MODE_BIT BIT(0)
|
||||
|
||||
#define PMI632_TYPEC_U_USB_WATER_PROTECTION_CFG_REG (TYPEC_BASE + 0x72)
|
||||
#define TYPEC_U_USB_WATER_PROTECTION_CFG_REG (TYPEC_BASE + 0x73)
|
||||
#define EN_MICRO_USB_WATER_PROTECTION_BIT BIT(4)
|
||||
#define MICRO_USB_DETECTION_ON_TIME_CFG_MASK GENMASK(3, 2)
|
||||
#define MICRO_USB_DETECTION_PERIOD_CFG_MASK GENMASK(1, 0)
|
||||
|
||||
#define PMI632_TYPEC_MICRO_USB_MODE_REG (TYPEC_BASE + 0x73)
|
||||
#define MICRO_USB_MODE_ONLY_BIT BIT(0)
|
||||
/********************************
|
||||
* MISC Peripheral Registers *
|
||||
********************************/
|
||||
#define TEMP_RANGE_STATUS_REG (MISC_BASE + 0x06)
|
||||
#define THERM_REG_ACTIVE_BIT BIT(6)
|
||||
#define TLIM_BIT BIT(5)
|
||||
#define TEMP_RANGE_MASK GENMASK(4, 1)
|
||||
#define ALERT_LEVEL_BIT BIT(4)
|
||||
#define TEMP_ABOVE_RANGE_BIT BIT(3)
|
||||
#define TEMP_WITHIN_RANGE_BIT BIT(2)
|
||||
#define TEMP_BELOW_RANGE_BIT BIT(1)
|
||||
#define THERMREG_DISABLED_BIT BIT(0)
|
||||
|
||||
#define DIE_TEMP_STATUS_REG (MISC_BASE + 0x07)
|
||||
#define DIE_TEMP_SHDN_BIT BIT(3)
|
||||
#define DIE_TEMP_RST_BIT BIT(2)
|
||||
#define DIE_TEMP_UB_BIT BIT(1)
|
||||
#define DIE_TEMP_LB_BIT BIT(0)
|
||||
|
||||
#define SKIN_TEMP_STATUS_REG (MISC_BASE + 0x08)
|
||||
#define SKIN_TEMP_SHDN_BIT BIT(3)
|
||||
#define SKIN_TEMP_RST_BIT BIT(2)
|
||||
#define SKIN_TEMP_UB_BIT BIT(1)
|
||||
#define SKIN_TEMP_LB_BIT BIT(0)
|
||||
|
||||
#define CONNECTOR_TEMP_STATUS_REG (MISC_BASE + 0x09)
|
||||
#define CONNECTOR_TEMP_SHDN_BIT BIT(3)
|
||||
#define CONNECTOR_TEMP_RST_BIT BIT(2)
|
||||
#define CONNECTOR_TEMP_UB_BIT BIT(1)
|
||||
#define CONNECTOR_TEMP_LB_BIT BIT(0)
|
||||
|
||||
#define SMB_TEMP_STATUS_REG (MISC_BASE + 0x0A)
|
||||
#define SMB_TEMP_SHDN_BIT BIT(3)
|
||||
#define SMB_TEMP_RST_BIT BIT(2)
|
||||
#define SMB_TEMP_UB_BIT BIT(1)
|
||||
#define SMB_TEMP_LB_BIT BIT(0)
|
||||
|
||||
#define BARK_BITE_WDOG_PET_REG (MISC_BASE + 0x43)
|
||||
#define BARK_BITE_WDOG_PET_BIT BIT(0)
|
||||
|
||||
#define AICL_CMD_REG (MISC_BASE + 0x44)
|
||||
#define RESTART_AICL_BIT BIT(1)
|
||||
#define RERUN_AICL_BIT BIT(0)
|
||||
|
||||
#define MISC_SMB_EN_CMD_REG (MISC_BASE + 0x48)
|
||||
#define SMB_EN_OVERRIDE_VALUE_BIT BIT(4)
|
||||
#define SMB_EN_OVERRIDE_BIT BIT(3)
|
||||
#define EN_STAT_CMD_BIT BIT(2)
|
||||
#define EN_CP_FPF_CMD_BIT BIT(1)
|
||||
#define EN_CP_CMD_BIT BIT(0)
|
||||
|
||||
#define WD_CFG_REG (MISC_BASE + 0x51)
|
||||
#define WATCHDOG_TRIGGER_AFP_EN_BIT BIT(7)
|
||||
#define BARK_WDOG_INT_EN_BIT BIT(6)
|
||||
#define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1)
|
||||
|
||||
#define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x53)
|
||||
#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7)
|
||||
#define SNARL_WDOG_TIMEOUT_MASK GENMASK(6, 4)
|
||||
#define SNARL_WDOG_TIMEOUT_SHIFT 4
|
||||
#define SNARL_WDOG_TMOUT_62P5MS 0x00
|
||||
#define SNARL_WDOG_TMOUT_1S 0x40
|
||||
#define SNARL_WDOG_TMOUT_8S 0x70
|
||||
#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
|
||||
#define BARK_WDOG_TIMEOUT_SHIFT 2
|
||||
#define BITE_WDOG_TIMEOUT_MASK GENMASK(1, 0)
|
||||
#define BITE_WDOG_TIMEOUT_8S 0x3
|
||||
#define MIN_WD_BARK_TIME 16
|
||||
|
||||
#define AICL_RERUN_TIME_CFG_REG (MISC_BASE + 0x61)
|
||||
#define AICL_RERUN_TIME_12S_VAL 0x01
|
||||
|
||||
#define MISC_THERMREG_SRC_CFG_REG (MISC_BASE + 0x70)
|
||||
#define THERMREG_SW_ICL_ADJUST_BIT BIT(7)
|
||||
#define DIE_ADC_SEL_BIT BIT(6)
|
||||
#define THERMREG_SMB_ADC_SRC_EN_BIT BIT(5)
|
||||
#define THERMREG_CONNECTOR_ADC_SRC_EN_BIT BIT(4)
|
||||
#define SKIN_ADC_CFG_BIT BIT(3)
|
||||
#define THERMREG_SKIN_ADC_SRC_EN_BIT BIT(2)
|
||||
#define THERMREG_DIE_ADC_SRC_EN_BIT BIT(1)
|
||||
#define THERMREG_DIE_CMP_SRC_EN_BIT BIT(0)
|
||||
|
||||
#define MISC_SMB_CFG_REG (MISC_BASE + 0x90)
|
||||
#define SMB_EN_SEL_BIT BIT(4)
|
||||
#define CP_EN_POLARITY_CFG_BIT BIT(3)
|
||||
#define STAT_POLARITY_CFG_BIT BIT(2)
|
||||
#define STAT_FUNCTION_CFG_BIT BIT(1)
|
||||
#define STAT_IRQ_PULSING_EN_BIT BIT(0)
|
||||
|
||||
#define DIE_REG_H_THRESHOLD_MSB_REG (MISC_BASE + 0xA0)
|
||||
|
||||
#define SMB_REG_H_THRESHOLD_MSB_REG (MISC_BASE + 0XBC)
|
||||
|
||||
/* SDAM regs */
|
||||
#define MISC_PBS_RT_STS_REG (MISC_PBS_BASE + 0x10)
|
||||
#define PULSE_SKIP_IRQ_BIT BIT(4)
|
||||
|
||||
#define SDAM_QC_DET_STATUS_REG 0x58
|
||||
#define SDAM_QC_ADC_LSB_REG 0x54
|
||||
|
||||
#endif /* __SMB5_CHARGER_REG_H */
|
||||
914
drivers/power/supply/qcom/step-chg-jeita.c
Normal file
914
drivers/power/supply/qcom/step-chg-jeita.c
Normal file
|
|
@ -0,0 +1,914 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "QCOM-STEPCHG: %s: " fmt, __func__
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pmic-voter.h>
|
||||
#include "step-chg-jeita.h"
|
||||
#include "battery-profile-loader.h"
|
||||
|
||||
#define STEP_CHG_VOTER "STEP_CHG_VOTER"
|
||||
#define JEITA_VOTER "JEITA_VOTER"
|
||||
|
||||
#define is_between(left, right, value) \
|
||||
(((left) >= (right) && (left) >= (value) \
|
||||
&& (value) >= (right)) \
|
||||
|| ((left) <= (right) && (left) <= (value) \
|
||||
&& (value) <= (right)))
|
||||
|
||||
struct step_chg_cfg {
|
||||
struct step_chg_jeita_param param;
|
||||
struct range_data fcc_cfg[MAX_STEP_CHG_ENTRIES];
|
||||
};
|
||||
|
||||
struct jeita_fcc_cfg {
|
||||
struct step_chg_jeita_param param;
|
||||
struct range_data fcc_cfg[MAX_STEP_CHG_ENTRIES];
|
||||
};
|
||||
|
||||
struct jeita_fv_cfg {
|
||||
struct step_chg_jeita_param param;
|
||||
struct range_data fv_cfg[MAX_STEP_CHG_ENTRIES];
|
||||
};
|
||||
|
||||
struct step_chg_info {
|
||||
struct device *dev;
|
||||
ktime_t step_last_update_time;
|
||||
ktime_t jeita_last_update_time;
|
||||
bool step_chg_enable;
|
||||
bool sw_jeita_enable;
|
||||
bool jeita_arb_en;
|
||||
bool config_is_read;
|
||||
bool step_chg_cfg_valid;
|
||||
bool sw_jeita_cfg_valid;
|
||||
bool soc_based_step_chg;
|
||||
bool ocv_based_step_chg;
|
||||
bool vbat_avg_based_step_chg;
|
||||
bool batt_missing;
|
||||
bool taper_fcc;
|
||||
int jeita_fcc_index;
|
||||
int jeita_fv_index;
|
||||
int step_index;
|
||||
int get_config_retry_count;
|
||||
|
||||
struct step_chg_cfg *step_chg_config;
|
||||
struct jeita_fcc_cfg *jeita_fcc_config;
|
||||
struct jeita_fv_cfg *jeita_fv_config;
|
||||
|
||||
struct votable *fcc_votable;
|
||||
struct votable *fv_votable;
|
||||
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;
|
||||
};
|
||||
|
||||
static struct step_chg_info *the_chip;
|
||||
|
||||
#define STEP_CHG_HYSTERISIS_DELAY_US 5000000 /* 5 secs */
|
||||
|
||||
#define BATT_HOT_DECIDEGREE_MAX 600
|
||||
#define GET_CONFIG_DELAY_MS 2000
|
||||
#define GET_CONFIG_RETRY_COUNT 50
|
||||
#define WAIT_BATT_ID_READY_MS 200
|
||||
|
||||
static bool is_batt_available(struct step_chg_info *chip)
|
||||
{
|
||||
if (!chip->batt_psy)
|
||||
chip->batt_psy = power_supply_get_by_name("battery");
|
||||
|
||||
if (!chip->batt_psy)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_bms_available(struct step_chg_info *chip)
|
||||
{
|
||||
if (!chip->bms_psy)
|
||||
chip->bms_psy = power_supply_get_by_name("bms");
|
||||
|
||||
if (!chip->bms_psy)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_usb_available(struct step_chg_info *chip)
|
||||
{
|
||||
if (!chip->usb_psy)
|
||||
chip->usb_psy = power_supply_get_by_name("usb");
|
||||
|
||||
if (!chip->usb_psy)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_input_present(struct step_chg_info *chip)
|
||||
{
|
||||
int rc = 0, input_present = 0;
|
||||
union power_supply_propval pval = {0, };
|
||||
|
||||
if (!chip->usb_psy)
|
||||
chip->usb_psy = power_supply_get_by_name("usb");
|
||||
if (chip->usb_psy) {
|
||||
rc = power_supply_get_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &pval);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't read USB Present status, rc=%d\n", rc);
|
||||
else
|
||||
input_present |= pval.intval;
|
||||
}
|
||||
|
||||
if (!chip->dc_psy)
|
||||
chip->dc_psy = power_supply_get_by_name("dc");
|
||||
if (chip->dc_psy) {
|
||||
rc = power_supply_get_property(chip->dc_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &pval);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't read DC Present status, rc=%d\n", rc);
|
||||
else
|
||||
input_present |= pval.intval;
|
||||
}
|
||||
|
||||
if (input_present)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int read_range_data_from_node(struct device_node *node,
|
||||
const char *prop_str, struct range_data *ranges,
|
||||
int max_threshold, u32 max_value)
|
||||
{
|
||||
int rc = 0, i, length, per_tuple_length, tuples;
|
||||
|
||||
if (!node || !prop_str || !ranges) {
|
||||
pr_err("Invalid parameters passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_count_elems_of_size(node, prop_str, sizeof(u32));
|
||||
if (rc < 0) {
|
||||
pr_err("Count %s failed, rc=%d\n", prop_str, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
length = rc;
|
||||
per_tuple_length = sizeof(struct range_data) / sizeof(u32);
|
||||
if (length % per_tuple_length) {
|
||||
pr_err("%s length (%d) should be multiple of %d\n",
|
||||
prop_str, length, per_tuple_length);
|
||||
return -EINVAL;
|
||||
}
|
||||
tuples = length / per_tuple_length;
|
||||
|
||||
if (tuples > MAX_STEP_CHG_ENTRIES) {
|
||||
pr_err("too many entries(%d), only %d allowed\n",
|
||||
tuples, MAX_STEP_CHG_ENTRIES);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32_array(node, prop_str,
|
||||
(u32 *)ranges, length);
|
||||
if (rc) {
|
||||
pr_err("Read %s failed, rc=%d\n", prop_str, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (i = 0; i < tuples; i++) {
|
||||
if (ranges[i].low_threshold >
|
||||
ranges[i].high_threshold) {
|
||||
pr_err("%s thresholds should be in ascendant ranges\n",
|
||||
prop_str);
|
||||
rc = -EINVAL;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
if (ranges[i - 1].high_threshold >
|
||||
ranges[i].low_threshold) {
|
||||
pr_err("%s thresholds should be in ascendant ranges\n",
|
||||
prop_str);
|
||||
rc = -EINVAL;
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
if (ranges[i].low_threshold > max_threshold)
|
||||
ranges[i].low_threshold = max_threshold;
|
||||
if (ranges[i].high_threshold > max_threshold)
|
||||
ranges[i].high_threshold = max_threshold;
|
||||
if (ranges[i].value > max_value)
|
||||
ranges[i].value = max_value;
|
||||
}
|
||||
|
||||
return rc;
|
||||
clean:
|
||||
memset(ranges, 0, tuples * sizeof(struct range_data));
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(read_range_data_from_node);
|
||||
|
||||
static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
|
||||
{
|
||||
struct device_node *batt_node, *profile_node;
|
||||
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, };
|
||||
|
||||
handle = of_get_property(chip->dev->of_node,
|
||||
"qcom,battery-data", NULL);
|
||||
if (!handle) {
|
||||
pr_debug("ignore getting sw-jeita/step charging settings from profile\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
batt_node = of_find_node_by_phandle(be32_to_cpup(handle));
|
||||
if (!batt_node) {
|
||||
pr_err("Get battery data node failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* bms_psy has not yet read the batt_id */
|
||||
if (batt_id_ohms < 0)
|
||||
return -EBUSY;
|
||||
|
||||
profile_node = of_batterydata_get_best_profile(batt_node,
|
||||
batt_id_ohms / 1000, NULL);
|
||||
if (IS_ERR(profile_node))
|
||||
return PTR_ERR(profile_node);
|
||||
|
||||
if (!profile_node) {
|
||||
pr_err("Couldn't find profile\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
rc = of_property_read_string(profile_node, "qcom,battery-type",
|
||||
&batt_type_str);
|
||||
if (rc < 0) {
|
||||
pr_err("battery type unavailable, rc:%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
pr_debug("battery: %s detected, getting sw-jeita/step charging settings\n",
|
||||
batt_type_str);
|
||||
|
||||
rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv",
|
||||
&max_fv_uv);
|
||||
if (rc < 0) {
|
||||
pr_err("max-voltage_uv reading failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(profile_node, "qcom,fastchg-current-ma",
|
||||
&max_fcc_ma);
|
||||
if (rc < 0) {
|
||||
pr_err("max-fastchg-current-ma reading failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
chip->taper_fcc = of_property_read_bool(profile_node, "qcom,taper-fcc");
|
||||
|
||||
chip->soc_based_step_chg =
|
||||
of_property_read_bool(profile_node, "qcom,soc-based-step-chg");
|
||||
if (chip->soc_based_step_chg) {
|
||||
chip->step_chg_config->param.psy_prop =
|
||||
POWER_SUPPLY_PROP_CAPACITY;
|
||||
chip->step_chg_config->param.prop_name = "SOC";
|
||||
chip->step_chg_config->param.hysteresis = 0;
|
||||
}
|
||||
|
||||
chip->ocv_based_step_chg =
|
||||
of_property_read_bool(profile_node, "qcom,ocv-based-step-chg");
|
||||
if (chip->ocv_based_step_chg) {
|
||||
chip->step_chg_config->param.psy_prop =
|
||||
POWER_SUPPLY_PROP_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;
|
||||
}
|
||||
|
||||
chip->vbat_avg_based_step_chg =
|
||||
of_property_read_bool(profile_node,
|
||||
"qcom,vbat-avg-based-step-chg");
|
||||
if (chip->vbat_avg_based_step_chg) {
|
||||
chip->step_chg_config->param.psy_prop =
|
||||
POWER_SUPPLY_PROP_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;
|
||||
}
|
||||
|
||||
chip->step_chg_cfg_valid = true;
|
||||
rc = read_range_data_from_node(profile_node,
|
||||
"qcom,step-chg-ranges",
|
||||
chip->step_chg_config->fcc_cfg,
|
||||
chip->soc_based_step_chg ? 100 : max_fv_uv,
|
||||
max_fcc_ma * 1000);
|
||||
if (rc < 0) {
|
||||
pr_debug("Read qcom,step-chg-ranges failed from battery profile, rc=%d\n",
|
||||
rc);
|
||||
chip->step_chg_cfg_valid = false;
|
||||
}
|
||||
|
||||
chip->sw_jeita_cfg_valid = true;
|
||||
rc = read_range_data_from_node(profile_node,
|
||||
"qcom,jeita-fcc-ranges",
|
||||
chip->jeita_fcc_config->fcc_cfg,
|
||||
BATT_HOT_DECIDEGREE_MAX, max_fcc_ma * 1000);
|
||||
if (rc < 0) {
|
||||
pr_debug("Read qcom,jeita-fcc-ranges failed from battery profile, rc=%d\n",
|
||||
rc);
|
||||
chip->sw_jeita_cfg_valid = false;
|
||||
}
|
||||
|
||||
rc = read_range_data_from_node(profile_node,
|
||||
"qcom,jeita-fv-ranges",
|
||||
chip->jeita_fv_config->fv_cfg,
|
||||
BATT_HOT_DECIDEGREE_MAX, max_fv_uv);
|
||||
if (rc < 0) {
|
||||
pr_debug("Read qcom,jeita-fv-ranges failed from battery profile, rc=%d\n",
|
||||
rc);
|
||||
chip->sw_jeita_cfg_valid = false;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void get_config_work(struct work_struct *work)
|
||||
{
|
||||
struct step_chg_info *chip = container_of(work,
|
||||
struct step_chg_info, get_config_work.work);
|
||||
int i, rc;
|
||||
|
||||
chip->config_is_read = false;
|
||||
rc = get_step_chg_jeita_setting_from_profile(chip);
|
||||
|
||||
if (rc < 0) {
|
||||
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",
|
||||
chip->get_config_retry_count);
|
||||
goto reschedule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chip->config_is_read = true;
|
||||
|
||||
for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
|
||||
pr_debug("step-chg-cfg: %duV(SoC) ~ %duV(SoC), %duA\n",
|
||||
chip->step_chg_config->fcc_cfg[i].low_threshold,
|
||||
chip->step_chg_config->fcc_cfg[i].high_threshold,
|
||||
chip->step_chg_config->fcc_cfg[i].value);
|
||||
for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
|
||||
pr_debug("jeita-fcc-cfg: %ddecidegree ~ %ddecidegre, %duA\n",
|
||||
chip->jeita_fcc_config->fcc_cfg[i].low_threshold,
|
||||
chip->jeita_fcc_config->fcc_cfg[i].high_threshold,
|
||||
chip->jeita_fcc_config->fcc_cfg[i].value);
|
||||
for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
|
||||
pr_debug("jeita-fv-cfg: %ddecidegree ~ %ddecidegre, %duV\n",
|
||||
chip->jeita_fv_config->fv_cfg[i].low_threshold,
|
||||
chip->jeita_fv_config->fv_cfg[i].high_threshold,
|
||||
chip->jeita_fv_config->fv_cfg[i].value);
|
||||
|
||||
return;
|
||||
|
||||
reschedule:
|
||||
schedule_delayed_work(&chip->get_config_work,
|
||||
msecs_to_jiffies(GET_CONFIG_DELAY_MS));
|
||||
|
||||
}
|
||||
|
||||
static int get_val(struct range_data *range, int hysteresis, int current_index,
|
||||
int threshold,
|
||||
int *new_index, int *val)
|
||||
{
|
||||
int i;
|
||||
|
||||
*new_index = -EINVAL;
|
||||
|
||||
/*
|
||||
* If the threshold is lesser than the minimum allowed range,
|
||||
* return -ENODATA.
|
||||
*/
|
||||
if (threshold < range[0].low_threshold)
|
||||
return -ENODATA;
|
||||
|
||||
/* First try to find the matching index without hysteresis */
|
||||
for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++) {
|
||||
if (!range[i].high_threshold && !range[i].low_threshold) {
|
||||
/* First invalid table entry; exit loop */
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_between(range[i].low_threshold,
|
||||
range[i].high_threshold, threshold)) {
|
||||
*new_index = i;
|
||||
*val = range[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If nothing was found, the threshold exceeds the max range for sure
|
||||
* as the other case where it is lesser than the min range is handled
|
||||
* at the very beginning of this function. Therefore, clip it to the
|
||||
* max allowed range value, which is the one corresponding to the last
|
||||
* valid entry in the battery profile data array.
|
||||
*/
|
||||
if (*new_index == -EINVAL) {
|
||||
if (i == 0) {
|
||||
/* Battery profile data array is completely invalid */
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
*new_index = (i - 1);
|
||||
*val = range[*new_index].value;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we don't have a current_index return this
|
||||
* newfound value. There is no hysterisis from out of range
|
||||
* to in range transition
|
||||
*/
|
||||
if (current_index == -EINVAL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check for hysteresis if it in the neighbourhood
|
||||
* of our current index.
|
||||
*/
|
||||
if (*new_index == current_index + 1) {
|
||||
if (threshold < range[*new_index].low_threshold + hysteresis) {
|
||||
/*
|
||||
* Stay in the current index, threshold is not higher
|
||||
* by hysteresis amount
|
||||
*/
|
||||
*new_index = current_index;
|
||||
*val = range[current_index].value;
|
||||
}
|
||||
} else if (*new_index == current_index - 1) {
|
||||
if (threshold > range[*new_index].high_threshold - hysteresis) {
|
||||
/*
|
||||
* stay in the current index, threshold is not lower
|
||||
* by hysteresis amount
|
||||
*/
|
||||
*new_index = current_index;
|
||||
*val = range[current_index].value;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TAPERED_STEP_CHG_FCC_REDUCTION_STEP_MA 50000 /* 50 mA */
|
||||
static void taper_fcc_step_chg(struct step_chg_info *chip, int index,
|
||||
int current_voltage)
|
||||
{
|
||||
u32 current_fcc, target_fcc;
|
||||
|
||||
if (index < 0) {
|
||||
pr_err("Invalid STEP CHG index\n");
|
||||
return;
|
||||
}
|
||||
|
||||
current_fcc = get_effective_result(chip->fcc_votable);
|
||||
target_fcc = chip->step_chg_config->fcc_cfg[index].value;
|
||||
|
||||
if (index == 0) {
|
||||
vote(chip->fcc_votable, STEP_CHG_VOTER, true, target_fcc);
|
||||
} else if (current_voltage >
|
||||
(chip->step_chg_config->fcc_cfg[index - 1].high_threshold +
|
||||
chip->step_chg_config->param.hysteresis)) {
|
||||
/*
|
||||
* Ramp down FCC in pre-configured steps till the current index
|
||||
* FCC configuration is reached, whenever the step charging
|
||||
* control parameter exceeds the high threshold of previous
|
||||
* step charging index configuration.
|
||||
*/
|
||||
vote(chip->fcc_votable, STEP_CHG_VOTER, true, max(target_fcc,
|
||||
current_fcc - TAPERED_STEP_CHG_FCC_REDUCTION_STEP_MA));
|
||||
} else if ((current_fcc >
|
||||
chip->step_chg_config->fcc_cfg[index - 1].value) &&
|
||||
(current_voltage >
|
||||
chip->step_chg_config->fcc_cfg[index - 1].low_threshold +
|
||||
chip->step_chg_config->param.hysteresis)) {
|
||||
/*
|
||||
* In case the step charging index switch to the next higher
|
||||
* index without FCCs saturation for the previous index, ramp
|
||||
* down FCC till previous index FCC configuration is reached.
|
||||
*/
|
||||
vote(chip->fcc_votable, STEP_CHG_VOTER, true,
|
||||
max(chip->step_chg_config->fcc_cfg[index - 1].value,
|
||||
current_fcc - TAPERED_STEP_CHG_FCC_REDUCTION_STEP_MA));
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_step_chg_config(struct step_chg_info *chip)
|
||||
{
|
||||
union power_supply_propval pval = {0, };
|
||||
int rc = 0, fcc_ua = 0, current_index;
|
||||
u64 elapsed_us;
|
||||
|
||||
elapsed_us = ktime_us_delta(ktime_get(), chip->step_last_update_time);
|
||||
/* skip processing, event too early */
|
||||
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);
|
||||
else
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
chip->step_chg_config->param.psy_prop, &pval);
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read %s property rc=%d\n",
|
||||
chip->step_chg_config->param.prop_name, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
current_index = chip->step_index;
|
||||
rc = get_val(chip->step_chg_config->fcc_cfg,
|
||||
chip->step_chg_config->param.hysteresis,
|
||||
chip->step_index,
|
||||
pval.intval,
|
||||
&chip->step_index,
|
||||
&fcc_ua);
|
||||
if (rc < 0) {
|
||||
/* remove the vote if no step-based fcc is found */
|
||||
if (chip->fcc_votable)
|
||||
vote(chip->fcc_votable, STEP_CHG_VOTER, false, 0);
|
||||
goto update_time;
|
||||
}
|
||||
|
||||
/* Do not drop step-chg index, if input supply is present */
|
||||
if (is_input_present(chip)) {
|
||||
if (chip->step_index < current_index)
|
||||
chip->step_index = current_index;
|
||||
} else {
|
||||
chip->step_index = 0;
|
||||
}
|
||||
|
||||
if (!chip->fcc_votable)
|
||||
chip->fcc_votable = find_votable("FCC");
|
||||
if (!chip->fcc_votable)
|
||||
return -EINVAL;
|
||||
|
||||
if (chip->taper_fcc) {
|
||||
taper_fcc_step_chg(chip, chip->step_index, pval.intval);
|
||||
} else {
|
||||
fcc_ua = chip->step_chg_config->fcc_cfg[chip->step_index].value;
|
||||
vote(chip->fcc_votable, STEP_CHG_VOTER, true, fcc_ua);
|
||||
}
|
||||
|
||||
pr_debug("%s = %d Step-FCC = %duA taper-fcc: %d\n",
|
||||
chip->step_chg_config->param.prop_name, pval.intval,
|
||||
get_client_vote(chip->fcc_votable, STEP_CHG_VOTER),
|
||||
chip->taper_fcc);
|
||||
|
||||
update_time:
|
||||
chip->step_last_update_time = ktime_get();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define JEITA_SUSPEND_HYST_UV 50000
|
||||
static int handle_jeita(struct step_chg_info *chip)
|
||||
{
|
||||
union power_supply_propval pval = {0, };
|
||||
int rc = 0, fcc_ua = 0, fv_uv = 0;
|
||||
u64 elapsed_us;
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_SW_JEITA_ENABLED, &pval);
|
||||
if (rc < 0)
|
||||
chip->sw_jeita_enable = false;
|
||||
else
|
||||
chip->sw_jeita_enable = pval.intval;
|
||||
|
||||
if (!chip->sw_jeita_enable || !chip->sw_jeita_cfg_valid) {
|
||||
if (chip->fcc_votable)
|
||||
vote(chip->fcc_votable, JEITA_VOTER, false, 0);
|
||||
if (chip->fv_votable)
|
||||
vote(chip->fv_votable, JEITA_VOTER, false, 0);
|
||||
if (chip->usb_icl_votable)
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
elapsed_us = ktime_us_delta(ktime_get(), chip->jeita_last_update_time);
|
||||
/* skip processing, event too early */
|
||||
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
|
||||
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",
|
||||
chip->jeita_fcc_config->param.prop_name, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = get_val(chip->jeita_fcc_config->fcc_cfg,
|
||||
chip->jeita_fcc_config->param.hysteresis,
|
||||
chip->jeita_fcc_index,
|
||||
pval.intval,
|
||||
&chip->jeita_fcc_index,
|
||||
&fcc_ua);
|
||||
if (rc < 0)
|
||||
fcc_ua = 0;
|
||||
|
||||
if (!chip->fcc_votable)
|
||||
chip->fcc_votable = find_votable("FCC");
|
||||
if (!chip->fcc_votable)
|
||||
/* changing FCC is a must */
|
||||
return -EINVAL;
|
||||
|
||||
vote(chip->fcc_votable, JEITA_VOTER, fcc_ua ? true : false, fcc_ua);
|
||||
|
||||
rc = get_val(chip->jeita_fv_config->fv_cfg,
|
||||
chip->jeita_fv_config->param.hysteresis,
|
||||
chip->jeita_fv_index,
|
||||
pval.intval,
|
||||
&chip->jeita_fv_index,
|
||||
&fv_uv);
|
||||
if (rc < 0)
|
||||
fv_uv = 0;
|
||||
|
||||
chip->fv_votable = find_votable("FV");
|
||||
if (!chip->fv_votable)
|
||||
goto update_time;
|
||||
|
||||
if (!chip->usb_icl_votable)
|
||||
chip->usb_icl_votable = find_votable("USB_ICL");
|
||||
|
||||
if (!chip->usb_icl_votable)
|
||||
goto set_jeita_fv;
|
||||
|
||||
/*
|
||||
* If JEITA float voltage is same as max-vfloat of battery then
|
||||
* skip any further VBAT specific checks.
|
||||
*/
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval);
|
||||
if (rc || (pval.intval == fv_uv)) {
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
|
||||
goto set_jeita_fv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Suspend USB input path if battery voltage is above
|
||||
* JEITA VFLOAT threshold.
|
||||
*/
|
||||
if (chip->jeita_arb_en && fv_uv > 0) {
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
|
||||
if (!rc && (pval.intval > fv_uv))
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, true, 0);
|
||||
else if (pval.intval < (fv_uv - JEITA_SUSPEND_HYST_UV))
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
|
||||
}
|
||||
|
||||
set_jeita_fv:
|
||||
vote(chip->fv_votable, JEITA_VOTER, fv_uv ? true : false, fv_uv);
|
||||
|
||||
update_time:
|
||||
chip->jeita_last_update_time = ktime_get();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_battery_insertion(struct step_chg_info *chip)
|
||||
{
|
||||
int rc;
|
||||
union power_supply_propval pval = {0, };
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Get battery present status failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (chip->batt_missing != (!pval.intval)) {
|
||||
chip->batt_missing = !pval.intval;
|
||||
pr_debug("battery %s detected\n",
|
||||
chip->batt_missing ? "removal" : "insertion");
|
||||
if (chip->batt_missing) {
|
||||
chip->step_chg_cfg_valid = false;
|
||||
chip->sw_jeita_cfg_valid = false;
|
||||
chip->get_config_retry_count = 0;
|
||||
} else {
|
||||
/*
|
||||
* Get config for the new inserted battery, delay
|
||||
* to make sure BMS has read out the batt_id.
|
||||
*/
|
||||
schedule_delayed_work(&chip->get_config_work,
|
||||
msecs_to_jiffies(WAIT_BATT_ID_READY_MS));
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void status_change_work(struct work_struct *work)
|
||||
{
|
||||
struct step_chg_info *chip = container_of(work,
|
||||
struct step_chg_info, status_change_work.work);
|
||||
int rc = 0;
|
||||
union power_supply_propval prop = {0, };
|
||||
|
||||
if (!is_batt_available(chip) || !is_bms_available(chip))
|
||||
goto exit_work;
|
||||
|
||||
handle_battery_insertion(chip);
|
||||
|
||||
/* skip elapsed_us debounce for handling battery temperature */
|
||||
rc = handle_jeita(chip);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't handle sw jeita rc = %d\n", rc);
|
||||
|
||||
rc = handle_step_chg_config(chip);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't handle step rc = %d\n", rc);
|
||||
|
||||
/* Remove stale votes on USB removal */
|
||||
if (is_usb_available(chip)) {
|
||||
prop.intval = 0;
|
||||
power_supply_get_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &prop);
|
||||
if (!prop.intval) {
|
||||
if (chip->usb_icl_votable)
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER,
|
||||
false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
exit_work:
|
||||
__pm_relax(chip->step_chg_ws);
|
||||
}
|
||||
|
||||
static int step_chg_notifier_call(struct notifier_block *nb,
|
||||
unsigned long ev, void *v)
|
||||
{
|
||||
struct power_supply *psy = v;
|
||||
struct step_chg_info *chip = container_of(nb, struct step_chg_info, nb);
|
||||
|
||||
if (ev != PSY_EVENT_PROP_CHANGED)
|
||||
return NOTIFY_OK;
|
||||
|
||||
if ((strcmp(psy->desc->name, "battery") == 0)
|
||||
|| (strcmp(psy->desc->name, "usb") == 0)) {
|
||||
__pm_stay_awake(chip->step_chg_ws);
|
||||
schedule_delayed_work(&chip->status_change_work, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int step_chg_register_notifier(struct step_chg_info *chip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
chip->nb.notifier_call = step_chg_notifier_call;
|
||||
rc = power_supply_reg_notifier(&chip->nb);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't register psy notifier rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qcom_step_chg_init(struct device *dev,
|
||||
bool step_chg_enable, bool sw_jeita_enable, bool jeita_arb_en)
|
||||
{
|
||||
int rc;
|
||||
struct step_chg_info *chip;
|
||||
|
||||
if (the_chip) {
|
||||
pr_err("Already initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->step_chg_ws = wakeup_source_register("qcom-step-chg");
|
||||
if (!chip->step_chg_ws)
|
||||
return -EINVAL;
|
||||
|
||||
chip->dev = dev;
|
||||
chip->step_chg_enable = step_chg_enable;
|
||||
chip->sw_jeita_enable = sw_jeita_enable;
|
||||
chip->jeita_arb_en = jeita_arb_en;
|
||||
chip->step_index = -EINVAL;
|
||||
chip->jeita_fcc_index = -EINVAL;
|
||||
chip->jeita_fv_index = -EINVAL;
|
||||
|
||||
chip->step_chg_config = devm_kzalloc(dev,
|
||||
sizeof(struct step_chg_cfg), GFP_KERNEL);
|
||||
if (!chip->step_chg_config)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->step_chg_config->param.psy_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
|
||||
chip->step_chg_config->param.prop_name = "VBATT";
|
||||
chip->step_chg_config->param.hysteresis = 100000;
|
||||
|
||||
chip->jeita_fcc_config = devm_kzalloc(dev,
|
||||
sizeof(struct jeita_fcc_cfg), GFP_KERNEL);
|
||||
chip->jeita_fv_config = devm_kzalloc(dev,
|
||||
sizeof(struct jeita_fv_cfg), GFP_KERNEL);
|
||||
if (!chip->jeita_fcc_config || !chip->jeita_fv_config)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->jeita_fcc_config->param.psy_prop = POWER_SUPPLY_PROP_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.prop_name = "BATT_TEMP";
|
||||
chip->jeita_fv_config->param.hysteresis = 10;
|
||||
|
||||
INIT_DELAYED_WORK(&chip->status_change_work, status_change_work);
|
||||
INIT_DELAYED_WORK(&chip->get_config_work, get_config_work);
|
||||
|
||||
rc = step_chg_register_notifier(chip);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't register psy notifier rc = %d\n", rc);
|
||||
goto release_wakeup_source;
|
||||
}
|
||||
|
||||
schedule_delayed_work(&chip->get_config_work,
|
||||
msecs_to_jiffies(GET_CONFIG_DELAY_MS));
|
||||
|
||||
the_chip = chip;
|
||||
|
||||
return 0;
|
||||
|
||||
release_wakeup_source:
|
||||
wakeup_source_unregister(chip->step_chg_ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void qcom_step_chg_deinit(void)
|
||||
{
|
||||
struct step_chg_info *chip = the_chip;
|
||||
|
||||
if (!chip)
|
||||
return;
|
||||
|
||||
cancel_delayed_work_sync(&chip->status_change_work);
|
||||
cancel_delayed_work_sync(&chip->get_config_work);
|
||||
power_supply_unreg_notifier(&chip->nb);
|
||||
wakeup_source_unregister(chip->step_chg_ws);
|
||||
the_chip = NULL;
|
||||
}
|
||||
30
drivers/power/supply/qcom/step-chg-jeita.h
Normal file
30
drivers/power/supply/qcom/step-chg-jeita.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __STEP_CHG_H__
|
||||
#define __STEP_CHG_H__
|
||||
|
||||
#define MAX_STEP_CHG_ENTRIES 8
|
||||
|
||||
struct step_chg_jeita_param {
|
||||
u32 psy_prop;
|
||||
char *prop_name;
|
||||
int hysteresis;
|
||||
bool use_bms;
|
||||
};
|
||||
|
||||
struct range_data {
|
||||
int low_threshold;
|
||||
int high_threshold;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
int qcom_step_chg_init(struct device *dev,
|
||||
bool step_chg_enable, bool sw_jeita_enable, bool jeita_arb_en);
|
||||
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__ */
|
||||
69
drivers/power/supply/qcom/storm-watch.c
Normal file
69
drivers/power/supply/qcom/storm-watch.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "storm-watch.h"
|
||||
|
||||
/**
|
||||
* is_storming(): Check if an event is storming
|
||||
*
|
||||
* @data: Data for tracking an event storm
|
||||
*
|
||||
* The return value will be true if a storm has been detected and
|
||||
* false if a storm was not detected.
|
||||
*/
|
||||
bool is_storming(struct storm_watch *data)
|
||||
{
|
||||
ktime_t curr_kt, delta_kt;
|
||||
bool is_storming = false;
|
||||
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
if (!data->enabled)
|
||||
return false;
|
||||
|
||||
/* max storm count must be greater than 0 */
|
||||
if (data->max_storm_count <= 0)
|
||||
return false;
|
||||
|
||||
/* the period threshold must be greater than 0ms */
|
||||
if (data->storm_period_ms <= 0)
|
||||
return false;
|
||||
|
||||
mutex_lock(&data->storm_lock);
|
||||
curr_kt = ktime_get_boottime();
|
||||
delta_kt = ktime_sub(curr_kt, data->last_kt);
|
||||
|
||||
if (ktime_to_ms(delta_kt) < data->storm_period_ms)
|
||||
data->storm_count++;
|
||||
else
|
||||
data->storm_count = 0;
|
||||
|
||||
if (data->storm_count > data->max_storm_count) {
|
||||
is_storming = true;
|
||||
data->storm_count = 0;
|
||||
}
|
||||
|
||||
data->last_kt = curr_kt;
|
||||
mutex_unlock(&data->storm_lock);
|
||||
return is_storming;
|
||||
}
|
||||
|
||||
void reset_storm_count(struct storm_watch *data)
|
||||
{
|
||||
mutex_lock(&data->storm_lock);
|
||||
data->storm_count = 0;
|
||||
mutex_unlock(&data->storm_lock);
|
||||
}
|
||||
|
||||
void update_storm_count(struct storm_watch *data, int max_count)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
mutex_lock(&data->storm_lock);
|
||||
data->max_storm_count = max_count;
|
||||
mutex_unlock(&data->storm_lock);
|
||||
}
|
||||
34
drivers/power/supply/qcom/storm-watch.h
Normal file
34
drivers/power/supply/qcom/storm-watch.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __STORM_WATCH_H
|
||||
#define __STORM_WATCH_H
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
/**
|
||||
* Data used to track an event storm.
|
||||
*
|
||||
* @storm_period_ms: The maximum time interval between two events. If this limit
|
||||
* is exceeded then the event chain will be broken and removed
|
||||
* from consideration for a storm.
|
||||
* @max_storm_count: The number of chained events required to trigger a storm.
|
||||
* @storm_count: The current number of chained events.
|
||||
* @last_kt: Kernel time of the last event seen.
|
||||
* @storm_lock: Mutex lock to protect storm_watch data.
|
||||
*/
|
||||
struct storm_watch {
|
||||
bool enabled;
|
||||
int storm_period_ms;
|
||||
int max_storm_count;
|
||||
int storm_count;
|
||||
ktime_t last_kt;
|
||||
struct mutex storm_lock;
|
||||
};
|
||||
|
||||
bool is_storming(struct storm_watch *data);
|
||||
void reset_storm_count(struct storm_watch *data);
|
||||
void update_storm_count(struct storm_watch *data, int max_count);
|
||||
#endif
|
||||
Loading…
Reference in a new issue