power: supply: qti_battery_charger: Apply xiaomi changes

From branch: zijin-s-oss

Change-Id: Ieb19795ff69250b2c425392e6a1e9b6c4dd814e1
This commit is contained in:
Arian 2022-10-13 19:56:07 +02:00 committed by Giovanni Ricca
parent 42d3441c27
commit a2ac6b286d
No known key found for this signature in database
3 changed files with 686 additions and 24 deletions

View File

@ -418,6 +418,42 @@ config QTI_BATTERY_CHARGER
To compile the driver as a module, choose M here: the module will be
called qti_battery_charger.
config BQ2597X
bool "BQ2597X charger"
depends on QTI_BATTERY_CHARGER
help
Say Y here to enable BQ2597X charger
config BQ_FG_1S
bool "BQ 1S battery cell config"
depends on QTI_BATTERY_CHARGER
help
Say Y here to enable BQ 1S battery cell
config BQ_FUEL_GAUGE
bool "BQ fuel gauge config"
depends on QTI_BATTERY_CHARGER
help
Say Y here to enable BQ fuel gauge
config DUAL_FUEL_GAUGE
bool "Dual fuel gauge"
depends on QTI_BATTERY_CHARGER
help
Say Y here to enable dual fuel gauge
config MI_WIRELESS
bool "mi wireless config"
depends on QTI_BATTERY_CHARGER
help
Say Y here to enable mi wireless
config RENOIR_FOR_BUILD
bool "renoir build debug"
depends on QTI_BATTERY_CHARGER
help
Say Y here to enable renoir build debug
config CHARGER_88PM860X
tristate "Marvell 88PM860x Charger driver"
depends on MFD_88PM860X && BATTERY_88PM860X

View File

@ -5,6 +5,7 @@
#define pr_fmt(fmt) "BATTERY_CHG: %s: " fmt, __func__
#include <drm/mi_disp_notifier.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
@ -21,6 +22,11 @@
#include <linux/soc/qcom/pmic_glink.h>
#include <linux/soc/qcom/battery_charger.h>
#if defined(CONFIG_BQ_FUEL_GAUGE)
#include <linux/hwid.h>
#include <linux/thermal.h>
#endif
#include "qti_battery_charger.h"
#include "qti_typec_class.h"
@ -36,6 +42,7 @@ static const int battery_prop_map[BATT_PROP_MAX] = {
[BATT_CURR_NOW] = POWER_SUPPLY_PROP_CURRENT_NOW,
[BATT_CHG_CTRL_LIM] = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
[BATT_CHG_CTRL_LIM_MAX] = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
[BATT_CONSTANT_CURRENT] = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
[BATT_TEMP] = POWER_SUPPLY_PROP_TEMP,
[BATT_TECHNOLOGY] = POWER_SUPPLY_PROP_TECHNOLOGY,
[BATT_CHG_COUNTER] = POWER_SUPPLY_PROP_CHARGE_COUNTER,
@ -67,6 +74,10 @@ static const int wls_prop_map[WLS_PROP_MAX] = {
[WLS_VOLT_MAX] = POWER_SUPPLY_PROP_VOLTAGE_MAX,
[WLS_CURR_NOW] = POWER_SUPPLY_PROP_CURRENT_NOW,
[WLS_CURR_MAX] = POWER_SUPPLY_PROP_CURRENT_MAX,
[WLS_TX_ADAPTER] = POWER_SUPPLY_PROP_TX_ADAPTER,
};
static const int xm_prop_map[XM_PROP_MAX] = {
};
static const unsigned int bcdev_usb_extcon_cable[] = {
@ -77,13 +88,14 @@ static const unsigned int bcdev_usb_extcon_cable[] = {
/* Standard usb_type definitions similar to power_supply_sysfs.c */
static const char * const power_supply_usb_type_text[] = {
"Unknown", "SDP", "DCP", "CDP", "ACA", "C",
"PD", "PD_DRP", "PD_PPS", "BrickID"
"Unknown", "USB", "USB_DCP", "USB_CDP", "USB_ACA", "USB_C",
"USB_PD", "PD_DRP", "PD_PPS", "BrickID", "USB_HVDCP",
"USB_HVDCP3","USB_HVDCP3P5", "USB_FLOAT"
};
/* Custom usb_type definitions */
static const char * const qc_power_supply_usb_type_text[] = {
"HVDCP", "HVDCP_3", "HVDCP_3P5"
"HVDCP", "HVDCP_3", "HVDCP_3P5","USB_FLOAT","HVDCP_3"
};
static int battery_chg_fw_write(struct battery_chg_dev *bcdev, void *data,
@ -139,14 +151,13 @@ static int battery_chg_write(struct battery_chg_dev *bcdev, void *data,
if (!rc) {
pr_err("Error, timed out sending message\n");
mutex_unlock(&bcdev->rw_lock);
return -ETIMEDOUT;
}
rc = 0;
}
mutex_unlock(&bcdev->rw_lock);
return rc;
return 0;
}
static int write_property_id(struct battery_chg_dev *bcdev,
@ -281,6 +292,13 @@ EXPORT_SYMBOL(qti_battery_charger_get_prop);
static bool validate_message(struct battery_charger_resp_msg *resp_msg,
size_t len)
{
struct xm_verify_digest_resp_msg *verify_digest_resp_msg = (struct xm_verify_digest_resp_msg *)resp_msg;
struct xm_ss_auth_resp_msg *ss_auth_resp_msg = (struct xm_ss_auth_resp_msg *)resp_msg;
if (len == sizeof(*verify_digest_resp_msg) || len == sizeof(*ss_auth_resp_msg)) {
return true;
}
if (len != sizeof(*resp_msg)) {
pr_err("Incorrect response length %zu for opcode %#x\n", len,
resp_msg->hdr.opcode);
@ -297,12 +315,17 @@ static bool validate_message(struct battery_charger_resp_msg *resp_msg,
return true;
}
static struct power_supply_desc usb_psy_desc;
#define MODEL_DEBUG_BOARD "Debug_Board"
static void handle_message(struct battery_chg_dev *bcdev, void *data,
size_t len)
{
struct battery_charger_resp_msg *resp_msg = data;
struct battery_model_resp_msg *model_resp_msg = data;
struct xm_verify_digest_resp_msg *verify_digest_resp_msg = data;
struct xm_ss_auth_resp_msg *ss_auth_resp_msg = data;
struct wls_fw_resp_msg *wls_fw_ver_resp_msg = data;
struct wireless_fw_check_resp *fw_check_msg;
struct wireless_fw_push_buf_resp *fw_resp_msg;
struct wireless_fw_update_status *fw_update_msg;
@ -336,22 +359,70 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data,
if (validate_message(resp_msg, len) &&
resp_msg->property_id < pst->prop_count) {
pst->prop[resp_msg->property_id] = resp_msg->value;
if (resp_msg->property_id == USB_ADAP_TYPE) {
switch (resp_msg->value) {
case ADAP_TYPE_DCP:
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP;
break;
case ADAP_TYPE_CDP:
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_CDP;
break;
case ADAP_TYPE_PD:
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
break;
case ADAP_TYPE_SDP:
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB;
break;
default:
break;
}
}
ack_set = true;
}
break;
case BC_WLS_STATUS_GET:
pst = &bcdev->psy_list[PSY_TYPE_WLS];
/* Handle model response uniquely as it's a string */
if (pst->version && len == sizeof(*wls_fw_ver_resp_msg)) {
memcpy(pst->version, wls_fw_ver_resp_msg->version, MAX_STR_LEN);
ack_set = true;
break;
}
if (validate_message(resp_msg, len) &&
resp_msg->property_id < pst->prop_count) {
pst->prop[resp_msg->property_id] = resp_msg->value;
ack_set = true;
}
break;
case BC_XM_STATUS_GET:
pst = &bcdev->psy_list[PSY_TYPE_XM];
/* Handle digest response uniquely as it's a string */
if (bcdev->digest && len == sizeof(*verify_digest_resp_msg)) {
memcpy(bcdev->digest, verify_digest_resp_msg->digest, BATTERY_DIGEST_LEN);
ack_set = true;
break;
}
if (bcdev->ss_auth_data && len == sizeof(*ss_auth_resp_msg)) {
memcpy(bcdev->ss_auth_data, ss_auth_resp_msg->data, BATTERY_SS_AUTH_DATA_LEN*sizeof(u32));
ack_set = true;
break;
}
if (validate_message(resp_msg, len) &&
resp_msg->property_id < pst->prop_count) {
pst->prop[resp_msg->property_id] = resp_msg->value;
ack_set = true;
}
break;
case BC_BATTERY_STATUS_SET:
case BC_USB_STATUS_SET:
case BC_WLS_STATUS_SET:
case BC_XM_STATUS_SET:
if (validate_message(data, len))
ack_set = true;
@ -465,8 +536,6 @@ static void battery_chg_update_uusb_type(struct battery_chg_dev *bcdev,
}
}
static struct power_supply_desc usb_psy_desc;
static void battery_chg_update_usb_type_work(struct work_struct *work)
{
struct battery_chg_dev *bcdev = container_of(work,
@ -496,6 +565,7 @@ static void battery_chg_update_usb_type_work(struct work_struct *work)
case QTI_POWER_SUPPLY_USB_TYPE_HVDCP:
case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3:
case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5:
case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3_CLASSB:
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP;
break;
case POWER_SUPPLY_USB_TYPE_CDP:
@ -513,13 +583,23 @@ static void battery_chg_update_usb_type_work(struct work_struct *work)
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
break;
default:
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB;
usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
break;
}
battery_chg_update_uusb_type(bcdev, pst->prop[USB_ADAP_TYPE]);
}
static void battery_chg_fb_notifier_work(struct work_struct *work)
{
struct battery_chg_dev *bcdev = container_of(work,
struct battery_chg_dev, fb_notifier_work);
int rc;
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM],
XM_PROP_FB_BLANK_STATE, bcdev->blank_state);
}
static void handle_notification(struct battery_chg_dev *bcdev, void *data,
size_t len)
{
@ -545,6 +625,9 @@ static void handle_notification(struct battery_chg_dev *bcdev, void *data,
case BC_WLS_STATUS_GET:
pst = &bcdev->psy_list[PSY_TYPE_WLS];
break;
case BC_XM_STATUS_GET:
schedule_delayed_work(&bcdev->xm_prop_change_work, 0);
break;
default:
break;
}
@ -559,7 +642,8 @@ static void handle_notification(struct battery_chg_dev *bcdev, void *data,
* unplugged).
*/
power_supply_changed(pst->psy);
pm_wakeup_dev_event(bcdev->dev, 50, true);
if (!bcdev->reverse_chg_flag)
pm_wakeup_dev_event(bcdev->dev, 50, true);
}
}
@ -627,6 +711,9 @@ static enum power_supply_property wls_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CURRENT_MAX,
#if defined(CONFIG_MI_WIRELESS)
POWER_SUPPLY_PROP_TX_ADAPTER,
#endif
};
static const struct power_supply_desc wls_psy_desc = {
@ -644,7 +731,7 @@ static const char *get_usb_type_name(u32 usb_type)
u32 i;
if (usb_type >= QTI_POWER_SUPPLY_USB_TYPE_HVDCP &&
usb_type <= QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5) {
usb_type <= QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3_CLASSB) {
for (i = 0; i < ARRAY_SIZE(qc_power_supply_usb_type_text);
i++) {
if (i == (usb_type - QTI_POWER_SUPPLY_USB_TYPE_HVDCP))
@ -700,6 +787,135 @@ static int usb_psy_set_icl(struct battery_chg_dev *bcdev, u32 prop_id, int val)
return rc;
}
typedef enum {
POWER_SUPPLY_USB_REAL_TYPE_HVDCP2=0x80,
POWER_SUPPLY_USB_REAL_TYPE_HVDCP3=0x81,
POWER_SUPPLY_USB_REAL_TYPE_HVDCP3P5=0x82,
POWER_SUPPLY_USB_REAL_TYPE_USB_FLOAT=0x83,
POWER_SUPPLY_USB_REAL_TYPE_HVDCP3_CLASSB=0x84,
} power_supply_usb_type;
struct quick_charge {
int adap_type;
enum power_supply_quick_charge_type adap_cap;
};
struct quick_charge adapter_cap[11] = {
{ POWER_SUPPLY_USB_TYPE_SDP, QUICK_CHARGE_NORMAL },
{ POWER_SUPPLY_USB_TYPE_DCP, QUICK_CHARGE_NORMAL },
{ POWER_SUPPLY_USB_TYPE_CDP, QUICK_CHARGE_NORMAL },
{ POWER_SUPPLY_USB_TYPE_ACA, QUICK_CHARGE_NORMAL },
{ POWER_SUPPLY_USB_REAL_TYPE_USB_FLOAT, QUICK_CHARGE_NORMAL },
{ POWER_SUPPLY_USB_TYPE_PD, QUICK_CHARGE_FAST },
{ POWER_SUPPLY_USB_REAL_TYPE_HVDCP2, QUICK_CHARGE_FAST },
{ POWER_SUPPLY_USB_REAL_TYPE_HVDCP3, QUICK_CHARGE_FAST },
{ POWER_SUPPLY_USB_REAL_TYPE_HVDCP3_CLASSB, QUICK_CHARGE_FLASH },
{ POWER_SUPPLY_USB_REAL_TYPE_HVDCP3P5, QUICK_CHARGE_FLASH },
{0, 0},
};
#define ADAPTER_NONE 0x0
#define ADAPTER_XIAOMI_QC3_20W 0x9
#define ADAPTER_XIAOMI_PD_20W 0xa
#define ADAPTER_XIAOMI_CAR_20W 0xb
#define ADAPTER_XIAOMI_PD_30W 0xc
#define ADAPTER_VOICE_BOX_30W 0xd
#define ADAPTER_XIAOMI_PD_50W 0xe
#define ADAPTER_XIAOMI_PD_60W 0xf
#define ADAPTER_XIAOMI_PD_100W 0x10
static u8 get_quick_charge_type(struct battery_chg_dev *bcdev)
{
int i = 0,verify_digiest = 0;
u8 rc;
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY];
enum power_supply_usb_type real_charger_type = 0;
int batt_health;
u32 apdo_max;
#if defined(CONFIG_MI_WIRELESS)
u32 tx_adapter = 0;
#endif
rc = read_property_id(bcdev, pst, BATT_HEALTH);
if (rc < 0)
return rc;
batt_health = pst->prop[BATT_HEALTH];
pst = &bcdev->psy_list[PSY_TYPE_USB];
rc = read_property_id(bcdev, pst, USB_REAL_TYPE);
if (rc < 0)
return rc;
real_charger_type = pst->prop[USB_REAL_TYPE];
pst = &bcdev->psy_list[PSY_TYPE_XM];
rc = read_property_id(bcdev, pst, XM_PROP_PD_VERIFED);
verify_digiest = pst->prop[XM_PROP_PD_VERIFED];
rc = read_property_id(bcdev, pst, XM_PROP_APDO_MAX);
apdo_max = pst->prop[XM_PROP_APDO_MAX];
#if defined(CONFIG_MI_WIRELESS)
rc = read_property_id(bcdev, pst, XM_PROP_TX_ADAPTER);
tx_adapter = pst->prop[XM_PROP_TX_ADAPTER];
#endif
if ((batt_health == POWER_SUPPLY_HEALTH_COLD) ||(batt_health == POWER_SUPPLY_HEALTH_WARM)
|| (batt_health == POWER_SUPPLY_HEALTH_OVERHEAT) || (batt_health == POWER_SUPPLY_HEALTH_OVERVOLTAGE))
return QUICK_CHARGE_NORMAL;
if (real_charger_type == POWER_SUPPLY_USB_TYPE_PD_PPS && verify_digiest == 1) {
if (apdo_max >= 50)
return QUICK_CHARGE_SUPER;
else
return QUICK_CHARGE_TURBE;
}
else if(real_charger_type == POWER_SUPPLY_USB_TYPE_PD_PPS)
return QUICK_CHARGE_FAST;
#if defined(CONFIG_MI_WIRELESS)
switch(tx_adapter)
{
case ADAPTER_NONE:
break;
case ADAPTER_XIAOMI_QC3_20W:
case ADAPTER_XIAOMI_PD_20W:
case ADAPTER_XIAOMI_CAR_20W:
case ADAPTER_XIAOMI_PD_30W:
case ADAPTER_VOICE_BOX_30W:
return QUICK_CHARGE_TURBE;
case ADAPTER_XIAOMI_PD_50W:
case ADAPTER_XIAOMI_PD_60W:
case ADAPTER_XIAOMI_PD_100W:
return QUICK_CHARGE_SUPER;
default:
return QUICK_CHARGE_NORMAL;
}
#endif
while (adapter_cap[i].adap_type != 0) {
if (real_charger_type == adapter_cap[i].adap_type) {
return adapter_cap[i].adap_cap;
}
i++;
}
return QUICK_CHARGE_NORMAL;
}
static int battery_psy_set_fcc(struct battery_chg_dev *bcdev, u32 prop_id, int val)
{
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY];
u32 temp;
int rc;
temp = val;
if (val < 0)
temp = UINT_MAX;
rc = write_property_id(bcdev, pst, prop_id, temp);
if (!rc)
pr_debug("Set FCC to %u\n", temp);
return rc;
}
static int usb_psy_get_prop(struct power_supply *psy,
enum power_supply_property prop,
union power_supply_propval *pval)
@ -709,6 +925,11 @@ static int usb_psy_get_prop(struct power_supply *psy,
int prop_id, rc;
pval->intval = -ENODATA;
if (prop == POWER_SUPPLY_PROP_QUICK_CHARGE_TYPE)
{
pval->intval = get_quick_charge_type(bcdev);
return 0;
}
prop_id = get_property_id(pst, prop);
if (prop_id < 0)
@ -770,6 +991,7 @@ static enum power_supply_property usb_props[] = {
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_USB_TYPE,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_QUICK_CHARGE_TYPE,
POWER_SUPPLY_PROP_SCOPE,
};
@ -824,7 +1046,11 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev,
int val)
{
int rc;
u32 fcc_ua, prev_fcc_ua;
//u32 fcc_ua, prev_fcc_ua;
if(val == bcdev->curr_thermal_level)
return 0;
pr_err("set thermal-level: %d num_thermal_levels: %d \n", val, bcdev->num_thermal_levels);
if (!bcdev->num_thermal_levels)
return 0;
@ -834,9 +1060,17 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev,
return -EINVAL;
}
if (val < 0 || val > bcdev->num_thermal_levels)
if (val < 0 || val >= bcdev->num_thermal_levels)
return -EINVAL;
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_BATTERY],
BATT_CHG_CTRL_LIM, val);
if (rc < 0)
pr_err("Failed to set ccl:%d, rc=%d\n", val, rc);
bcdev->curr_thermal_level = val;
#if 0
fcc_ua = bcdev->thermal_levels[val];
prev_fcc_ua = bcdev->thermal_fcc_ua;
bcdev->thermal_fcc_ua = fcc_ua;
@ -846,6 +1080,7 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev,
bcdev->curr_thermal_level = val;
else
bcdev->thermal_fcc_ua = prev_fcc_ua;
#endif
return rc;
}
@ -907,10 +1142,19 @@ static int battery_psy_set_prop(struct power_supply *psy,
const union power_supply_propval *pval)
{
struct battery_chg_dev *bcdev = power_supply_get_drvdata(psy);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY];
int prop_id, rc = 0;
prop_id = get_property_id(pst, prop);
if (prop_id < 0)
return prop_id;
switch (prop) {
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
return battery_psy_set_charge_current(bcdev, pval->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
rc = battery_psy_set_fcc(bcdev, prop_id, pval->intval);
break;
default:
return -EINVAL;
}
@ -923,6 +1167,7 @@ static int battery_psy_prop_is_writeable(struct power_supply *psy,
{
switch (prop) {
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
return 1;
default:
break;
@ -943,6 +1188,7 @@ static enum power_supply_property battery_props[] = {
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_CHARGE_COUNTER,
@ -959,6 +1205,9 @@ static enum power_supply_property battery_props[] = {
static const struct power_supply_desc batt_psy_desc = {
.name = "battery",
#if defined(CONFIG_BQ_FUEL_GAUGE)
.no_thermal = true,
#endif
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = battery_props,
.num_properties = ARRAY_SIZE(battery_props),
@ -967,10 +1216,52 @@ static const struct power_supply_desc batt_psy_desc = {
.property_is_writeable = battery_psy_prop_is_writeable,
};
#if defined(CONFIG_BQ_FUEL_GAUGE)
static int power_supply_read_temp(struct thermal_zone_device *tzd,
int *temp)
{
struct power_supply *psy;
struct battery_chg_dev *bcdev = NULL;
struct psy_state *pst = NULL;
int rc = 0, batt_temp;
static int last_temp;
ktime_t time_now;
static ktime_t last_read_time;
s64 delta;
WARN_ON(tzd == NULL);
psy = tzd->devdata;
bcdev = power_supply_get_drvdata(psy);
pst = &bcdev->psy_list[PSY_TYPE_XM];
time_now = ktime_get();
delta = ktime_ms_delta(time_now, last_read_time);
if(delta < 5000){
batt_temp = last_temp;
} else {
rc = read_property_id(bcdev, pst, XM_PROP_THERMAL_TEMP);
batt_temp = pst->prop[XM_PROP_THERMAL_TEMP];
last_temp = batt_temp;
last_read_time = time_now;
}
*temp = batt_temp * 1000;
pr_err("batt_thermal temp:%d ,delta:%ld blank_state=%d chg_type=%s tl:=%d ffc:=%d, pd_verifed:=%d\n",
batt_temp,delta, bcdev->blank_state, power_supply_usb_type_text[pst->prop[XM_PROP_REAL_TYPE]],
bcdev->curr_thermal_level, pst->prop[XM_PROP_FASTCHGMODE], pst->prop[XM_PROP_PD_VERIFED]);
return 0;
}
static struct thermal_zone_device_ops psy_tzd_ops = {
.get_temp = power_supply_read_temp,
};
#endif
static int battery_chg_init_psy(struct battery_chg_dev *bcdev)
{
struct power_supply_config psy_cfg = {};
int rc;
struct power_supply *psy;
psy_cfg.drv_data = bcdev;
psy_cfg.of_node = bcdev->dev->of_node;
@ -982,6 +1273,11 @@ static int battery_chg_init_psy(struct battery_chg_dev *bcdev)
pr_err("Failed to register battery power supply, rc=%d\n", rc);
return rc;
}
psy = bcdev->psy_list[PSY_TYPE_BATTERY].psy;
#if defined(CONFIG_BQ_FUEL_GAUGE)
psy->tzd = thermal_zone_device_register(psy->desc->name,
0, 0, psy, &psy_tzd_ops, NULL, 0, 0);
#endif
bcdev->psy_list[PSY_TYPE_USB].psy =
devm_power_supply_register(bcdev->dev, &usb_psy_desc, &psy_cfg);
@ -1534,10 +1830,20 @@ static ssize_t ship_mode_en_store(struct class *c, struct class_attribute *attr,
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct battery_charger_ship_mode_req_msg msg = { { 0 } };
int rc =0;
if (kstrtobool(buf, &bcdev->ship_mode_en))
return -EINVAL;
msg.hdr.owner = MSG_OWNER_BC;
msg.hdr.type = MSG_TYPE_REQ_RESP;
msg.hdr.opcode = BC_SHIP_MODE_REQ_SET;
msg.ship_mode_type = SHIP_MODE_PMIC;
rc = battery_chg_write(bcdev, &msg, sizeof(msg));
if (rc < 0)
pr_err("Failed to write ship mode: %d\n", rc);
return count;
}
@ -1607,8 +1913,8 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev)
{
struct device_node *node = bcdev->dev->of_node;
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY];
int i, rc, len;
u32 prev, val;
int rc, len;
//u32 prev,i, val;
of_property_read_string(node, "qcom,wireless-fw-name",
&bcdev->wls_fw_name);
@ -1620,6 +1926,7 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev)
len = rc;
#if 0
rc = read_property_id(bcdev, pst, BATT_CHG_CTRL_LIM_MAX);
if (rc < 0) {
pr_err("Failed to read prop BATT_CHG_CTRL_LIM_MAX, rc=%d\n",
@ -1643,6 +1950,7 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev)
prev = val;
}
#endif
bcdev->thermal_levels = devm_kcalloc(bcdev->dev, len + 1,
sizeof(*bcdev->thermal_levels),
@ -1664,29 +1972,23 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev)
return rc;
}
bcdev->num_thermal_levels = len;
bcdev->num_thermal_levels = MAX_THERMAL_LEVEL;
bcdev->thermal_fcc_ua = pst->prop[BATT_CHG_CTRL_LIM_MAX];
bcdev->support_wireless_charge = of_property_read_bool(node, "mi,support-wireless");
bcdev->support_2s_charging = of_property_read_bool(node, "mi,support-2s-charging");
return 0;
}
static int battery_chg_ship_mode(struct notifier_block *nb, unsigned long code,
void *unused)
{
struct battery_charger_notify_msg msg_notify = { { 0 } };
struct battery_charger_ship_mode_req_msg msg = { { 0 } };
struct battery_chg_dev *bcdev = container_of(nb, struct battery_chg_dev,
reboot_notifier);
int rc;
msg_notify.hdr.owner = MSG_OWNER_BC;
msg_notify.hdr.type = MSG_TYPE_NOTIFY;
msg_notify.hdr.opcode = BC_SHUTDOWN_NOTIFY;
rc = battery_chg_write(bcdev, &msg_notify, sizeof(msg_notify));
if (rc < 0)
pr_err("Failed to send shutdown notification rc=%d\n", rc);
if (!bcdev->ship_mode_en)
return NOTIFY_DONE;
@ -1704,6 +2006,61 @@ static int battery_chg_ship_mode(struct notifier_block *nb, unsigned long code,
return NOTIFY_DONE;
}
static int battery_chg_shutdown(struct notifier_block *nb, unsigned long code,
void *unused)
{
struct battery_charger_shutdown_req_msg msg = { { 0 } };
struct battery_chg_dev *bcdev = container_of(nb, struct battery_chg_dev,
shutdown_notifier);
int rc;
msg.hdr.owner = MSG_OWNER_BC;
msg.hdr.type = MSG_TYPE_REQ_RESP;
msg.hdr.opcode = BC_SHUTDOWN_REQ_SET;
if (code == SYS_POWER_OFF || code == SYS_RESTART) {
pr_err("start adsp shutdown\n");
rc = battery_chg_write(bcdev, &msg, sizeof(msg));
if (rc < 0)
pr_emerg("Failed to write ship mode: %d\n", rc);
}
return NOTIFY_DONE;
}
#define FB_BLANK 1
#define FB_UNBLANK 0
static int fb_notifier_callback(struct notifier_block *nb,
unsigned long val, void *data)
{
struct battery_chg_dev *bcdev = container_of(nb, struct battery_chg_dev,
fb_notifier);
struct mi_disp_notifier *evdata = data;
unsigned int blank;
int rc;
if(val != MI_DISP_DPMS_EVENT)
return NOTIFY_OK;
if (evdata && evdata->data && bcdev) {
blank = *(int *)(evdata->data);
pr_debug("val:%lu,blank:%u\n", val, blank);
if ((blank == MI_DISP_DPMS_POWERDOWN ||
blank == MI_DISP_DPMS_LP1 || blank == MI_DISP_DPMS_LP2)) {
bcdev->blank_state = FB_BLANK;
} else if (blank == MI_DISP_DPMS_ON) {
bcdev->blank_state = FB_UNBLANK;
}
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM],
XM_PROP_FB_BLANK_STATE, bcdev->blank_state);
if (rc < 0)
return rc;
}
return NOTIFY_OK;
}
static int register_extcon_conn_type(struct battery_chg_dev *bcdev)
{
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
@ -1752,6 +2109,9 @@ static int battery_chg_probe(struct platform_device *pdev)
struct pmic_glink_client_data client_data = { };
int rc, i;
dev_err(dev, "battery_chg_probe start\n");
msleep(50);
bcdev = devm_kzalloc(&pdev->dev, sizeof(*bcdev), GFP_KERNEL);
if (!bcdev)
return -ENOMEM;
@ -1768,6 +2128,10 @@ static int battery_chg_probe(struct platform_device *pdev)
bcdev->psy_list[PSY_TYPE_WLS].prop_count = WLS_PROP_MAX;
bcdev->psy_list[PSY_TYPE_WLS].opcode_get = BC_WLS_STATUS_GET;
bcdev->psy_list[PSY_TYPE_WLS].opcode_set = BC_WLS_STATUS_SET;
bcdev->psy_list[PSY_TYPE_XM].map = xm_prop_map;
bcdev->psy_list[PSY_TYPE_XM].prop_count = XM_PROP_MAX;
bcdev->psy_list[PSY_TYPE_XM].opcode_get = BC_XM_STATUS_GET;
bcdev->psy_list[PSY_TYPE_XM].opcode_set = BC_XM_STATUS_SET;
for (i = 0; i < PSY_TYPE_MAX; i++) {
bcdev->psy_list[i].prop =
@ -1781,6 +2145,17 @@ static int battery_chg_probe(struct platform_device *pdev)
devm_kzalloc(&pdev->dev, MAX_STR_LEN, GFP_KERNEL);
if (!bcdev->psy_list[PSY_TYPE_BATTERY].model)
return -ENOMEM;
bcdev->digest=
devm_kzalloc(&pdev->dev, BATTERY_DIGEST_LEN, GFP_KERNEL);
if (!bcdev->digest)
return -ENOMEM;
bcdev->ss_auth_data=
devm_kzalloc(&pdev->dev, BATTERY_SS_AUTH_DATA_LEN * sizeof(u32), GFP_KERNEL);
if (!bcdev->ss_auth_data)
return -ENOMEM;
bcdev->psy_list[PSY_TYPE_WLS].version =
devm_kzalloc(&pdev->dev, MAX_STR_LEN, GFP_KERNEL);
mutex_init(&bcdev->rw_lock);
init_completion(&bcdev->ack);
@ -1788,6 +2163,8 @@ static int battery_chg_probe(struct platform_device *pdev)
init_completion(&bcdev->fw_update_ack);
INIT_WORK(&bcdev->subsys_up_work, battery_chg_subsys_up_work);
INIT_WORK(&bcdev->usb_type_work, battery_chg_update_usb_type_work);
INIT_WORK(&bcdev->fb_notifier_work, battery_chg_fb_notifier_work);
atomic_set(&bcdev->state, PMIC_GLINK_STATE_UP);
bcdev->dev = dev;
@ -1811,6 +2188,22 @@ static int battery_chg_probe(struct platform_device *pdev)
bcdev->reboot_notifier.priority = 255;
register_reboot_notifier(&bcdev->reboot_notifier);
/* register shutdown notifier to do something before shutdown */
bcdev->shutdown_notifier.notifier_call = battery_chg_shutdown;
bcdev->shutdown_notifier.priority = 255;
register_reboot_notifier(&bcdev->shutdown_notifier);
bcdev->fb_notifier.notifier_call = fb_notifier_callback;
#if !defined(CONFIG_RENOIR_FOR_BUILD)
rc = mi_disp_register_client(&bcdev->fb_notifier);
#else
rc = 0;
#endif
if (rc < 0) {
dev_err(dev, "Failed to register disp notifier rc=%d\n", rc);
goto error;
}
rc = battery_chg_parse_dt(bcdev);
if (rc < 0) {
dev_err(dev, "Failed to parse dt rc=%d\n", rc);
@ -1850,11 +2243,26 @@ static int battery_chg_probe(struct platform_device *pdev)
schedule_work(&bcdev->usb_type_work);
schedule_delayed_work(&bcdev->charger_debug_info_print_work, 5 * HZ);
bcdev->slave_fg_verify_flag = false;
bcdev->shutdown_delay_en = true;
bcdev->reverse_chg_flag = 0;
bcdev->hw_version_build = 0;
#if defined(CONFIG_BQ_FUEL_GAUGE)
bcdev->hw_version_build = get_hw_id_value();
#endif
dev_err(dev, "battery_chg_probe done\n");
return 0;
error:
bcdev->initialized = false;
complete(&bcdev->ack);
pmic_glink_unregister_client(bcdev->client);
#if !defined(CONFIG_RENOIR_FOR_BUILD)
mi_disp_unregister_client(&bcdev->fb_notifier);
#endif
unregister_reboot_notifier(&bcdev->reboot_notifier);
return rc;
}
@ -1867,6 +2275,9 @@ static int battery_chg_remove(struct platform_device *pdev)
device_init_wakeup(bcdev->dev, false);
debugfs_remove_recursive(bcdev->debugfs_dir);
class_unregister(&bcdev->battery_class);
#if !defined(CONFIG_RENOIR_FOR_BUILD)
mi_disp_unregister_client(&bcdev->fb_notifier);
#endif
unregister_reboot_notifier(&bcdev->reboot_notifier);
qti_typec_class_deinit(bcdev->typec_class);
rc = pmic_glink_unregister_client(bcdev->client);
@ -1877,16 +2288,36 @@ static int battery_chg_remove(struct platform_device *pdev)
return 0;
}
static int chg_suspend(struct device *dev)
{
//struct battery_chg_dev *bcdev = dev_get_drvdata(dev);
pr_err("chg suspend\n");
return 0;
}
static int chg_resume(struct device *dev)
{
//struct battery_chg_dev *bcdev = dev_get_drvdata(dev);
pr_err("chg resume\n");
return 0;
}
static const struct of_device_id battery_chg_match_table[] = {
{ .compatible = "qcom,battery-charger" },
{},
};
static const struct dev_pm_ops chg_pm_ops = {
.resume = chg_resume,
.suspend = chg_suspend,
};
static struct platform_driver battery_chg_driver = {
.driver = {
.name = "qti_battery_charger",
.of_match_table = battery_chg_match_table,
.pm = &chg_pm_ops,
},
.probe = battery_chg_probe,
.remove = battery_chg_remove,

View File

@ -9,6 +9,8 @@
#define MSG_TYPE_NOTIFY 2
/* opcode for battery charger */
#define BC_XM_STATUS_GET 0x50
#define BC_XM_STATUS_SET 0x51
#define BC_SET_NOTIFY_REQ 0x04
#define BC_NOTIFY_IND 0x07
#define BC_BATTERY_STATUS_GET 0x30
@ -18,6 +20,7 @@
#define BC_WLS_STATUS_GET 0x34
#define BC_WLS_STATUS_SET 0x35
#define BC_SHIP_MODE_REQ_SET 0x36
#define BC_SHUTDOWN_REQ_SET 0x37
#define BC_WLS_FW_CHECK_UPDATE 0x40
#define BC_WLS_FW_PUSH_BUF_REQ 0x41
#define BC_WLS_FW_UPDATE_STATUS_RESP 0x42
@ -35,6 +38,20 @@
#define WLS_FW_BUF_SIZE 128
#define DEFAULT_RESTRICT_FCC_UA 1000000
#if defined(CONFIG_BQ_FG_1S)
#define BATTERY_DIGEST_LEN 32
#else
#define BATTERY_DIGEST_LEN 20
#endif
#define BATTERY_SS_AUTH_DATA_LEN 4
#define ADAP_TYPE_SDP 1
#define ADAP_TYPE_CDP 3
#define ADAP_TYPE_DCP 2
#define ADAP_TYPE_PD 6
#define MAX_THERMAL_LEVEL 16
enum usb_connector_type {
USB_CONNECTOR_TYPE_TYPEC,
USB_CONNECTOR_TYPE_MICRO_USB,
@ -44,6 +61,7 @@ enum psy_type {
PSY_TYPE_BATTERY,
PSY_TYPE_USB,
PSY_TYPE_WLS,
PSY_TYPE_XM,
PSY_TYPE_MAX,
};
@ -66,6 +84,7 @@ enum battery_property_id {
BATT_CURR_NOW,
BATT_CHG_CTRL_LIM,
BATT_CHG_CTRL_LIM_MAX,
BATT_CONSTANT_CURRENT,
BATT_TEMP,
BATT_TECHNOLOGY,
BATT_CHG_COUNTER,
@ -108,13 +127,148 @@ enum wireless_property_id {
WLS_CURR_MAX,
WLS_TYPE,
WLS_BOOST_EN,
WLS_FW_VER,
WLS_TX_ADAPTER,
WLS_REGISTER,
WLS_INPUT_CURR,
WLS_PROP_MAX,
};
enum xm_property_id {
XM_PROP_RESISTANCE_ID,
XM_PROP_VERIFY_DIGEST,
XM_PROP_CONNECTOR_TEMP,
XM_PROP_AUTHENTIC,
XM_PROP_CHIP_OK,
#if defined(CONFIG_DUAL_FUEL_GAUGE)
XM_PROP_SLAVE_CHIP_OK,
XM_PROP_SLAVE_AUTHENTIC,
XM_PROP_FG1_VOL,
XM_PROP_FG1_SOC,
XM_PROP_FG1_TEMP,
XM_PROP_FG1_IBATT,
XM_PROP_FG2_VOL,
XM_PROP_FG2_SOC,
XM_PROP_FG2_TEMP,
XM_PROP_FG2_IBATT,
XM_PROP_FG2_QMAX,
XM_PROP_FG2_RM,
XM_PROP_FG2_FCC,
XM_PROP_FG2_SOH,
XM_PROP_FG2_FCC_SOH,
XM_PROP_FG2_CYCLE,
XM_PROP_FG2_FAST_CHARGE,
XM_PROP_FG2_CURRENT_MAX,
XM_PROP_FG2_VOL_MAX,
XM_PROP_FG2_TSIM,
XM_PROP_FG2_TAMBIENT,
XM_PROP_FG2_TREMQ,
XM_PROP_FG2_TFULLQ,
XM_PROP_IS_OLD_HW,
#endif
XM_PROP_SOC_DECIMAL,
XM_PROP_SOC_DECIMAL_RATE,
XM_PROP_SHUTDOWN_DELAY,
XM_PROP_VBUS_DISABLE,
XM_PROP_CC_ORIENTATION,
XM_PROP_SLAVE_BATT_PRESENT,
#if defined(CONFIG_BQ2597X)
XM_PROP_BQ2597X_CHIP_OK,
XM_PROP_BQ2597X_SLAVE_CHIP_OK,
XM_PROP_BQ2597X_BUS_CURRENT,
XM_PROP_BQ2597X_SLAVE_BUS_CURRENT,
XM_PROP_BQ2597X_BUS_DELTA,
XM_PROP_BQ2597X_BUS_VOLTAGE,
XM_PROP_BQ2597X_BATTERY_PRESENT,
XM_PROP_BQ2597X_SLAVE_BATTERY_PRESENT,
XM_PROP_BQ2597X_BATTERY_VOLTAGE,
XM_PROP_COOL_MODE,
#endif
XM_PROP_BT_TRANSFER_START,
XM_PROP_MASTER_SMB1396_ONLINE,
XM_PROP_MASTER_SMB1396_IIN,
XM_PROP_SLAVE_SMB1396_ONLINE,
XM_PROP_SLAVE_SMB1396_IIN,
XM_PROP_SMB_IIN_DIFF,
/* wireless charge infor */
XM_PROP_TX_MACL,
XM_PROP_TX_MACH,
XM_PROP_RX_CRL,
XM_PROP_RX_CRH,
XM_PROP_RX_CEP,
XM_PROP_BT_STATE,
XM_PROP_REVERSE_CHG_MODE,
XM_PROP_REVERSE_CHG_STATE,
XM_PROP_WLS_FW_STATE,
XM_PROP_RX_VOUT,
XM_PROP_RX_VRECT,
XM_PROP_RX_IOUT,
XM_PROP_TX_ADAPTER,
XM_PROP_OP_MODE,
XM_PROP_WLS_DIE_TEMP,
XM_PROP_WLS_CAR_ADAPTER,
XM_PROP_WLS_TX_SPEED,
/**********************/
XM_PROP_INPUT_SUSPEND,
XM_PROP_REAL_TYPE,
/*used for pd authentic*/
XM_PROP_VERIFY_PROCESS,
XM_PROP_VDM_CMD_CHARGER_VERSION,
XM_PROP_VDM_CMD_CHARGER_VOLTAGE,
XM_PROP_VDM_CMD_CHARGER_TEMP,
XM_PROP_VDM_CMD_SESSION_SEED,
XM_PROP_VDM_CMD_AUTHENTICATION,
XM_PROP_VDM_CMD_VERIFIED,
XM_PROP_VDM_CMD_REMOVE_COMPENSATION,
XM_PROP_VDM_CMD_REVERSE_AUTHEN,
XM_PROP_CURRENT_STATE,
XM_PROP_ADAPTER_ID,
XM_PROP_ADAPTER_SVID,
XM_PROP_PD_VERIFED,
XM_PROP_PDO2,
XM_PROP_UVDM_STATE,
/* use for MI SMART INTERCHG */
XM_PROP_VDM_CMD_SINK_SOC,
/*****************/
XM_PROP_WLS_BIN,
XM_PROP_FASTCHGMODE,
XM_PROP_APDO_MAX,
XM_PROP_THERMAL_REMOVE,
XM_PROP_VOTER_DEBUG,
XM_PROP_FG_RM,
XM_PROP_WLSCHARGE_CONTROL_LIMIT,
XM_PROP_MTBF_CURRENT,
XM_PROP_FAKE_TEMP,
XM_PROP_QBG_VBAT,
XM_PROP_QBG_VPH_PWR,
XM_PROP_QBG_TEMP,
XM_PROP_FB_BLANK_STATE,
XM_PROP_THERMAL_TEMP,
XM_PROP_TYPEC_MODE,
XM_PROP_NIGHT_CHARGING,
XM_PROP_SMART_BATT,
XM_PROP_FG1_QMAX,
XM_PROP_FG1_RM,
XM_PROP_FG1_FCC,
XM_PROP_FG1_SOH,
XM_PROP_FG1_FCC_SOH,
XM_PROP_FG1_CYCLE,
XM_PROP_FG1_FAST_CHARGE,
XM_PROP_FG1_CURRENT_MAX,
XM_PROP_FG1_VOL_MAX,
XM_PROP_FG1_TSIM,
XM_PROP_FG1_TAMBIENT,
XM_PROP_FG1_TREMQ,
XM_PROP_FG1_TFULLQ,
XM_PROP_FG_UPDATE_TIME,
XM_PROP_MAX,
};
enum {
QTI_POWER_SUPPLY_USB_TYPE_HVDCP = 0x80,
QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3,
QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5,
QTI_POWER_SUPPLY_USB_TYPE_USB_FLOAT,
QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3_CLASSB,
};
struct battery_charger_set_notify_msg {
@ -144,12 +298,27 @@ struct battery_charger_resp_msg {
u32 ret_code;
};
struct wls_fw_resp_msg {
struct pmic_glink_hdr hdr;
u32 property_id;
u32 value;
char version[MAX_STR_LEN];
};
struct battery_model_resp_msg {
struct pmic_glink_hdr hdr;
u32 property_id;
char model[MAX_STR_LEN];
};
struct xm_verify_digest_resp_msg {
struct pmic_glink_hdr hdr;
u32 property_id;
u8 digest[BATTERY_DIGEST_LEN];
bool slave_fg;
};
struct wireless_fw_check_req {
struct pmic_glink_hdr hdr;
u32 fw_version;
@ -192,9 +361,20 @@ struct battery_charger_ship_mode_req_msg {
u32 ship_mode_type;
};
struct battery_charger_shutdown_req_msg {
struct pmic_glink_hdr hdr;
};
struct xm_ss_auth_resp_msg {
struct pmic_glink_hdr hdr;
u32 property_id;
u32 data[BATTERY_SS_AUTH_DATA_LEN];
};
struct psy_state {
struct power_supply *psy;
char *model;
char *version;
const int *map;
u32 *prop;
u32 prop_count;
@ -213,15 +393,20 @@ struct battery_chg_dev {
struct completion fw_update_ack;
struct psy_state psy_list[PSY_TYPE_MAX];
struct dentry *debugfs_dir;
u8 *digest;
bool slave_fg_verify_flag;
u32 *ss_auth_data;
/* extcon for VBUS/ID notification for USB for micro USB */
struct extcon_dev *extcon;
u32 *thermal_levels;
const char *wls_fw_name;
int curr_thermal_level;
int curr_wlsthermal_level;
int num_thermal_levels;
atomic_t state;
struct work_struct subsys_up_work;
struct work_struct usb_type_work;
struct work_struct fb_notifier_work;
int fake_soc;
bool block_tx;
bool ship_mode_en;
@ -230,13 +415,23 @@ struct battery_chg_dev {
u32 wls_fw_version;
u16 wls_fw_crc;
struct notifier_block reboot_notifier;
struct notifier_block fb_notifier;
struct notifier_block shutdown_notifier;
int blank_state;
u32 thermal_fcc_ua;
u32 restrict_fcc_ua;
u32 last_fcc_ua;
u32 usb_icl_ua;
u32 reverse_chg_flag;
u32 hw_version_build;
u32 connector_type;
u32 usb_prev_mode;
bool restrict_chg_en;
bool shutdown_delay_en;
bool support_wireless_charge;
bool support_2s_charging;
struct delayed_work xm_prop_change_work;
struct delayed_work charger_debug_info_print_work;
/* To track the driver initialization status */
bool initialized;
};