From a42be9610366682811b1398b129490bead1c3868 Mon Sep 17 00:00:00 2001 From: Arian Date: Tue, 7 Mar 2023 18:12:51 +0100 Subject: [PATCH] power: supply: qti_battery_charger: Import xiaomi changes From mayfly-s-oss and moved new attributes to qti_battery_charger_xiaomi Change-Id: I5de84bc9274c113d39051943d4caf5701c3d65cf --- drivers/power/supply/Kconfig | 30 + drivers/power/supply/Makefile | 2 +- drivers/power/supply/qti_battery_charger.c | 666 ++- drivers/power/supply/qti_battery_charger.h | 290 ++ .../power/supply/qti_battery_charger_xiaomi.c | 4248 +++++++++++++++++ 5 files changed, 5169 insertions(+), 67 deletions(-) create mode 100644 drivers/power/supply/qti_battery_charger_xiaomi.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 38ab0a357447..7b86fc52b376 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -823,6 +823,36 @@ config CHARGER_BQ256XX charge management and system power path management devices for single cell Li-ion and Li-polymer batteries. +config BQ_FG_2S + tristate "2s battery fuel gauge support" + help + Say Y here to have support for 2s battery fuel gauge. + +config MI_WIRELESS + tristate "mi wirless config" + help + Say Y here to enable mi wireless + +config BQ_FUEL_GAUGE + tristate "BQ fuel gauge config" + help + Say y here to enable Bq fuel gauge + +config BQ_CLOUD_AUTHENTICATION + tristate "BQ cloud thentication config" + help + Say Y here to enable Bq cloud thentication + +config DUAL_FUEL_GAUGE + tristate "BQ fuel gauge config" + help + Say y here to enable Bq fuel gauge + +config BQ_FG_UPDATE + tristate "BQ fuel gauge config" + help + Say y here to enable Bq fuel gauge + source "drivers/power/supply/qcom/Kconfig" endif # POWER_SUPPLY diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index 189bff64c4c9..53389a32d513 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -98,7 +98,7 @@ obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o obj-$(CONFIG_CHARGER_BD99954) += bd99954-charger.o obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o obj-$(CONFIG_QTI_BATTERY_CHARGER) += qti_battery_charger_main.o -qti_battery_charger_main-y += qti_battery_charger.o qti_typec_class.o +qti_battery_charger_main-y += qti_battery_charger.o qti_battery_charger_xiaomi.o qti_typec_class.o obj-$(CONFIG_RN5T618_POWER) += rn5t618_power.o obj-$(CONFIG_SCHGM_FLASH) += schgm-flash.o obj-$(CONFIG_CHARGER_BQ256XX) += bq256xx_charger.o diff --git a/drivers/power/supply/qti_battery_charger.c b/drivers/power/supply/qti_battery_charger.c index ecea4f9cebff..ab170a7c4299 100644 --- a/drivers/power/supply/qti_battery_charger.c +++ b/drivers/power/supply/qti_battery_charger.c @@ -23,6 +23,14 @@ #include #include #include +#include +#include + +#if defined(CONFIG_DRM_PANEL) +static struct drm_panel *active_panel,*active_panel_sec; +static void *cookie = NULL, *cookie1=NULL; +static int blank_state = 1, sec_blank_state = 1; +#endif #include "qti_battery_charger.h" #include "qti_typec_class.h" @@ -39,6 +47,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, @@ -70,6 +79,7 @@ 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_BOOST_EN] = POWER_SUPPLY_PROP_PRESENT, }; static const unsigned int bcdev_usb_extcon_cable[] = { @@ -81,12 +91,16 @@ 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" + "PD", "PD_DRP", "PD_PPS", "BrickID", "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 const int xm_prop_map[XM_PROP_MAX] = { + }; static RAW_NOTIFIER_HEAD(hboost_notifier); @@ -133,7 +147,7 @@ static int battery_chg_fw_write(struct battery_chg_dev *bcdev, void *data, return rc; } -static int battery_chg_write(struct battery_chg_dev *bcdev, void *data, +int battery_chg_write(struct battery_chg_dev *bcdev, void *data, int len) { int rc; @@ -189,7 +203,7 @@ static int battery_chg_write(struct battery_chg_dev *bcdev, void *data, return rc; } -static int write_property_id(struct battery_chg_dev *bcdev, +int write_property_id(struct battery_chg_dev *bcdev, struct psy_state *pst, u32 prop_id, u32 val) { struct battery_charger_req_msg req_msg = { { 0 } }; @@ -208,7 +222,7 @@ static int write_property_id(struct battery_chg_dev *bcdev, return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); } -static int read_property_id(struct battery_chg_dev *bcdev, +int read_property_id(struct battery_chg_dev *bcdev, struct psy_state *pst, u32 prop_id) { struct battery_charger_req_msg req_msg = { { 0 } }; @@ -227,7 +241,7 @@ static int read_property_id(struct battery_chg_dev *bcdev, return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); } -static int get_property_id(struct psy_state *pst, +int get_property_id(struct psy_state *pst, enum power_supply_property prop) { u32 i; @@ -390,6 +404,13 @@ EXPORT_SYMBOL(qti_battery_charger_set_prop); static bool validate_message(struct battery_chg_dev *bcdev, 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); @@ -413,6 +434,10 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data, { 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 wls_debug_msg *wls_debug_data = 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; @@ -458,10 +483,42 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data, 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(bcdev, resp_msg, len) && + resp_msg->property_id < pst->prop_count) { + pst->prop[resp_msg->property_id] = resp_msg->value; + ack_set = true; + } + /* 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 (len == sizeof(*wls_debug_data)) { + memcpy(bcdev->wls_debug_data, wls_debug_data->data, MAX_STR_LEN); + ack_set = true; + break; + } break; case BC_BATTERY_STATUS_SET: case BC_USB_STATUS_SET: case BC_WLS_STATUS_SET: + case BC_XM_STATUS_SET: if (validate_message(bcdev, data, len)) ack_set = true; @@ -470,7 +527,8 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data, case BC_DISABLE_NOTIFY_REQ: case BC_SHUTDOWN_NOTIFY: case BC_SHIP_MODE_REQ_SET: - /* Always ACK response for notify or ship_mode request */ + case BC_SHUTDOWN_REQ_SET: + /* Always ACK response for notify or ship_mode or shutdown request */ ack_set = true; break; case BC_WLS_FW_CHECK_UPDATE: @@ -626,7 +684,7 @@ 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; } @@ -639,9 +697,11 @@ static void battery_chg_check_status_work(struct work_struct *work) struct battery_chg_dev, battery_check_work); struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY]; + struct psy_state *usb_pst = &bcdev->psy_list[PSY_TYPE_USB]; + struct psy_state *wireless_pst = &bcdev->psy_list[PSY_TYPE_WLS]; int rc; - rc = read_property_id(bcdev, pst, BATT_STATUS); + /*rc = read_property_id(bcdev, pst, BATT_STATUS); if (rc < 0) { pr_err("Failed to read BATT_STATUS, rc=%d\n", rc); return; @@ -650,6 +710,23 @@ static void battery_chg_check_status_work(struct work_struct *work) if (pst->prop[BATT_STATUS] == POWER_SUPPLY_STATUS_CHARGING) { pr_debug("Battery is charging\n"); return; + }*/ + + rc = read_property_id(bcdev, usb_pst, USB_ONLINE); + if (rc < 0) { + pr_err("Failed to read USB_ONLINE, rc=%d\n", rc); + return; + } + + rc = read_property_id(bcdev, wireless_pst, WLS_ONLINE); + if (rc < 0) { + pr_debug("Failed to read WLS_ONLINE, rc=%d\n", rc); + return; + } + + if (usb_pst->prop[USB_ONLINE] == 0 && wireless_pst->prop[WLS_ONLINE] == 0) { + pr_debug("usb and wireless is not online\n"); + return; } rc = read_property_id(bcdev, pst, BATT_CAPACITY); @@ -658,7 +735,11 @@ static void battery_chg_check_status_work(struct work_struct *work) return; } +#if defined(CONFIG_BQ_FUEL_GAUGE) + if(pst->prop[BATT_CAPACITY] / 100 > 0) { +#else if (DIV_ROUND_CLOSEST(pst->prop[BATT_CAPACITY], 100) > 0) { +#endif pr_debug("Battery SOC is > 0\n"); return; } @@ -683,8 +764,9 @@ static void battery_chg_check_status_work(struct work_struct *work) pr_emerg("Initiating a shutdown in 100 ms\n"); msleep(100); - pr_emerg("Attempting kernel_power_off: Battery voltage low\n"); - kernel_power_off(); + bcdev->report_power_absent = true; + /* pr_emerg("Attempting kernel_power_off: Battery voltage low\n"); + kernel_power_off();*/ } static void handle_notification(struct battery_chg_dev *bcdev, void *data, @@ -722,6 +804,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; } @@ -736,7 +821,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); } } @@ -767,7 +853,7 @@ static int battery_chg_callback(void *priv, void *data, size_t len) return 0; } -static int wls_psy_get_prop(struct power_supply *psy, +int wls_psy_get_prop(struct power_supply *psy, enum power_supply_property prop, union power_supply_propval *pval) { @@ -777,6 +863,11 @@ static int wls_psy_get_prop(struct power_supply *psy, pval->intval = -ENODATA; + if (prop == POWER_SUPPLY_PROP_PRESENT) { + pval->intval = bcdev->boost_mode; + return 0; + } + prop_id = get_property_id(pst, prop); if (prop_id < 0) return prop_id; @@ -787,6 +878,13 @@ static int wls_psy_get_prop(struct power_supply *psy, pval->intval = pst->prop[prop_id]; + if (prop == POWER_SUPPLY_PROP_ONLINE) { + if (pval->intval == 1 && bcdev->report_power_absent) + pval->intval = 0; + if (bcdev->debug_work_en == 0 && pval->intval == 1) + schedule_delayed_work(&bcdev->charger_debug_info_print_work, 5 * HZ); + } + return 0; } @@ -809,6 +907,7 @@ static enum power_supply_property wls_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_PRESENT, }; static const struct power_supply_desc wls_psy_desc = { @@ -821,12 +920,12 @@ static const struct power_supply_desc wls_psy_desc = { .property_is_writeable = wls_psy_prop_is_writeable, }; -static const char *get_usb_type_name(u32 usb_type) +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)) @@ -887,7 +986,7 @@ static int usb_psy_set_icl(struct battery_chg_dev *bcdev, u32 prop_id, int val) return rc; } -static int usb_psy_get_prop(struct power_supply *psy, +int usb_psy_get_prop(struct power_supply *psy, enum power_supply_property prop, union power_supply_propval *pval) { @@ -909,6 +1008,13 @@ static int usb_psy_get_prop(struct power_supply *psy, if (prop == POWER_SUPPLY_PROP_TEMP) pval->intval = DIV_ROUND_CLOSEST((int)pval->intval, 10); + if (prop == POWER_SUPPLY_PROP_ONLINE) { + if (pval->intval == 1 && bcdev->report_power_absent) + pval->intval = 0; + if (bcdev->debug_work_en == 0 && pval->intval == 1) + schedule_delayed_work(&bcdev->charger_debug_info_print_work, 5 * HZ); + } + return 0; } @@ -1011,7 +1117,12 @@ 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; + struct psy_state *pst = NULL; + + pst = &bcdev->psy_list[PSY_TYPE_XM]; + + pr_info("set thermal-level: %d num_thermal_levels: %d \n", val, bcdev->num_thermal_levels); if (!bcdev->num_thermal_levels) return 0; @@ -1021,9 +1132,20 @@ 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; + + pr_err("chg_type=%s tl:=%d ffc:=%d, pd_verifed:=%d\n",get_usb_type_name(pst->prop[XM_PROP_REAL_TYPE]), + bcdev->curr_thermal_level, pst->prop[XM_PROP_FASTCHGMODE], pst->prop[XM_PROP_PD_VERIFED]); + +#if 0 if (bcdev->thermal_fcc_step == 0) fcc_ua = bcdev->thermal_levels[val]; else @@ -1038,6 +1160,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; } @@ -1072,13 +1195,20 @@ static int battery_psy_get_prop(struct power_supply *psy, pval->strval = pst->model; break; case POWER_SUPPLY_PROP_CAPACITY: +#if defined(CONFIG_BQ_FUEL_GAUGE) + pval->intval = pst->prop[prop_id] / 100; +#else pval->intval = DIV_ROUND_CLOSEST(pst->prop[prop_id], 100); - if (IS_ENABLED(CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG) && - (bcdev->fake_soc >= 0 && bcdev->fake_soc <= 100)) +#endif + if (bcdev->fake_soc >= 0 && bcdev->fake_soc <= 100) pval->intval = bcdev->fake_soc; break; case POWER_SUPPLY_PROP_TEMP: +#if defined(CONFIG_BQ_FUEL_GAUGE) + pval->intval = pst->prop[prop_id] / 10; +#else pval->intval = DIV_ROUND_CLOSEST((int)pst->prop[prop_id], 10); +#endif break; case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: pval->intval = bcdev->curr_thermal_level; @@ -1086,6 +1216,13 @@ static int battery_psy_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: pval->intval = bcdev->num_thermal_levels; break; + case POWER_SUPPLY_PROP_STATUS: + pval->intval = pst->prop[prop_id]; + /* report discharging to user space to shutdown device */ + if (pval->intval == POWER_SUPPLY_STATUS_CHARGING && + bcdev->report_power_absent) + pval->intval = POWER_SUPPLY_STATUS_DISCHARGING; + break; default: pval->intval = pst->prop[prop_id]; break; @@ -1094,15 +1231,43 @@ static int battery_psy_get_prop(struct power_supply *psy, return rc; } +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; + + pr_info("Kernel Set FCC to %u\n", val); + + 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 battery_psy_set_prop(struct power_supply *psy, enum power_supply_property prop, 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; } @@ -1115,6 +1280,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; @@ -1135,6 +1301,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, @@ -1151,6 +1318,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), @@ -1159,9 +1329,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 = 0, first_init = 1; + 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 < 10000 && !first_init){ + batt_temp = last_temp; + } else { + if(bcdev->support_soc_update != true) + rc = read_property_id(bcdev, pst, XM_PROP_THERMAL_TEMP); + batt_temp = pst->prop[XM_PROP_THERMAL_TEMP]; + last_read_time = time_now; + first_init = 0; + } + + *temp = batt_temp * 100; + if( batt_temp!= last_temp) { + last_temp = batt_temp; + pr_err("batt_thermal temp:%d ,delta:%ld rc=%d\n",batt_temp,delta, rc); + } + 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 = {}; + struct power_supply *psy; int rc; psy_cfg.drv_data = bcdev; @@ -1198,6 +1411,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 return 0; } @@ -1629,7 +1847,7 @@ static ssize_t fake_soc_store(struct class *c, struct class_attribute *attr, bcdev->fake_soc = val; pr_debug("Set fake soc to %d\n", val); - if (IS_ENABLED(CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG) && pst->psy) + if (pst->psy) power_supply_changed(pst->psy); return count; @@ -1788,10 +2006,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; } @@ -1825,7 +2053,18 @@ static struct attribute *battery_class_attrs[] = { &class_attr_usb_typec_compliant.attr, NULL, }; -ATTRIBUTE_GROUPS(battery_class); + +static const struct attribute_group battery_class_group = { + .attrs = battery_class_attrs, +}; + +extern const struct attribute_group xiaomi_battery_class_group; + +static const struct attribute_group *battery_class_groups[] = { + &battery_class_group, + &xiaomi_battery_class_group, + NULL, +}; static struct attribute *battery_class_no_wls_attrs[] = { &class_attr_soh.attr, @@ -1954,29 +2193,24 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) } } - 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_2s_charging = of_property_read_bool(node, "mi,support-2s-charging"); + bcdev->support_dual_panel = of_property_read_bool(node, "mi,support-dual-panel"); + bcdev->support_soc_update = of_property_read_bool(node, "mi,support-soc-update"); + 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; @@ -1986,6 +2220,7 @@ static int battery_chg_ship_mode(struct notifier_block *nb, unsigned long code, msg.ship_mode_type = SHIP_MODE_PMIC; if (code == SYS_POWER_OFF) { + pr_err("set adsp shipmode\n"); rc = battery_chg_write(bcdev, &msg, sizeof(msg)); if (rc < 0) pr_emerg("Failed to write ship mode: %d\n", rc); @@ -1994,6 +2229,47 @@ static int battery_chg_ship_mode(struct notifier_block *nb, unsigned long code, return NOTIFY_DONE; } +static int register_extcon_conn_type(struct battery_chg_dev *bcdev) +{ + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB]; + int rc; + + rc = read_property_id(bcdev, pst, USB_CONNECTOR_TYPE); + if (rc < 0) { + pr_err("Failed to read prop USB_CONNECTOR_TYPE, rc=%d\n", + rc); + return rc; + } + + bcdev->connector_type = pst->prop[USB_CONNECTOR_TYPE]; + bcdev->usb_prev_mode = EXTCON_NONE; + + bcdev->extcon = devm_extcon_dev_allocate(bcdev->dev, + bcdev_usb_extcon_cable); + if (IS_ERR(bcdev->extcon)) { + rc = PTR_ERR(bcdev->extcon); + pr_err("Failed to allocate extcon device rc=%d\n", rc); + return rc; + } + + rc = devm_extcon_dev_register(bcdev->dev, bcdev->extcon); + if (rc < 0) { + pr_err("Failed to register extcon device rc=%d\n", rc); + return rc; + } + rc = extcon_set_property_capability(bcdev->extcon, EXTCON_USB, + EXTCON_PROP_USB_SS); + rc |= extcon_set_property_capability(bcdev->extcon, + EXTCON_USB_HOST, EXTCON_PROP_USB_SS); + if (rc < 0) + pr_err("failed to configure extcon capabilities rc=%d\n", rc); + else + pr_debug("Registered extcon, connector_type %s\n", + bcdev->connector_type ? "uusb" : "Typec"); + + return rc; +} + static void panel_event_notifier_callback(enum panel_event_notifier_tag tag, struct panel_event_notification *notification, void *data) { @@ -2067,45 +2343,238 @@ static int battery_chg_register_panel_notifier(struct battery_chg_dev *bcdev) return 0; } -static int register_extcon_conn_type(struct battery_chg_dev *bcdev) +#if defined(CONFIG_BQ_FG_UPDATE) +#define BATT_UPDATE_PERIOD_10S 10 +#define BATT_UPDATE_PERIOD_20S 20 +static void xm_batt_update_work(struct work_struct *work) { - struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB]; + struct battery_chg_dev *bcdev = container_of(work, struct battery_chg_dev, batt_update_work.work); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int interval = BATT_UPDATE_PERIOD_10S; + int rc = 0; + int state = 0; + + rc = read_property_id(bcdev, pst, XM_PROP_THERMAL_TEMP); + state = blank_state & sec_blank_state; + if (state) + interval = BATT_UPDATE_PERIOD_20S; + + pr_err("batt_update_work: batt_temp:%d blank_state:%d\n", + pst->prop[XM_PROP_THERMAL_TEMP] * 100, state); + schedule_delayed_work(&bcdev->batt_update_work, interval * HZ); +} +#endif + +#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) +static int charge_check_panel(struct device_node *np) +{ + int i; + int count; + struct device_node *node; + struct drm_panel *panel; + + count = of_count_phandle_with_args(np, "panel", NULL); + if (count <= 0) + return 0; + + for (i = 0; i < count; i++) { + node = of_parse_phandle(np, "panel", i); + panel = of_drm_find_panel(node); + of_node_put(node); + if (!IS_ERR(panel)) { + active_panel = panel; + return 0; + }else{ + active_panel = NULL; + } + } + return PTR_ERR(panel); +} + +static void screen_state_for_charge_callback(enum panel_event_notifier_tag notifier_tag, + struct panel_event_notification *notification, void *client_data) +{ + struct battery_chg_dev *bcdev = client_data; + if(!notification) { + printk(KERN_ERR "%s:Invalid notification\n", __func__); + return; + } + + if(notification->notif_data.early_trigger) { + return; + } + + if(notifier_tag == PANEL_EVENT_NOTIFICATION_PRIMARY) { + switch (notification->notif_type) { + case DRM_PANEL_EVENT_UNBLANK: + blank_state = 0; + break; + case DRM_PANEL_EVENT_BLANK: + case DRM_PANEL_EVENT_BLANK_LP: + blank_state = 1; + break; + case DRM_PANEL_EVENT_FPS_CHANGE: + return; + default: + return; + } + printk(KERN_ERR "%s, primary blank_state = %d\n", __func__, blank_state); + if (!bcdev->support_soc_update) + schedule_work(&bcdev->notify_blankstate_work); + } else if(notifier_tag == PANEL_EVENT_NOTIFICATION_SECONDARY) { + switch (notification->notif_type) { + case DRM_PANEL_EVENT_UNBLANK: + sec_blank_state = 0; + break; + case DRM_PANEL_EVENT_BLANK: + case DRM_PANEL_EVENT_BLANK_LP: + sec_blank_state = 1; + break; + case DRM_PANEL_EVENT_FPS_CHANGE: + return; + default: + return; + } + printk(KERN_ERR "%s, second blank_state = %d\n", __func__, sec_blank_state); + if (!bcdev->support_soc_update) + schedule_work(&bcdev->notify_blankstate_work); + } + return; + +} + +static void notify_blankstate_changed_work(struct work_struct *work) +{ + struct battery_chg_dev *bcdev = container_of(work, struct battery_chg_dev, notify_blankstate_work); + int rc; + int state; + state = blank_state & sec_blank_state; + printk(KERN_ERR "%s:write BLANK_STATE = %d,blank_state =%d,sec_blank_state =%d\n", __func__,state,blank_state,sec_blank_state); + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_FB_BLANK_STATE, state); + if(rc < 0) + printk(KERN_ERR "%s:write BLANK_STATE failed\n", __func__); + printk(KERN_ERR "%s:write BLANK_STATE sucdess\n", __func__); + +} +static void qti_battery_register_panel_notifier_work(struct work_struct *work) +{ + struct device_node *node; + struct battery_chg_dev *pvt_data = container_of(work, struct battery_chg_dev, panel_notify_register_work.work); + int error = 0; + static retry_count = 3; + + node = of_find_node_by_name(NULL, "charge-screen"); + if (!node) { + pr_err("%s ERROR: Cannot find node with panel!", __func__); + return; + } + + error = charge_check_panel(node); + if (error == -EPROBE_DEFER) + pr_err("%s ERROR: Cannot fine panel of node!", __func__); + + if (active_panel) { + cookie = panel_event_notifier_register(PANEL_EVENT_NOTIFICATION_PRIMARY, + PANEL_EVENT_NOTIFIER_CLIENT_CHARGE, active_panel, + screen_state_for_charge_callback, (void *)pvt_data); + pr_err("ERROR: cookie:%s", cookie); + if (IS_ERR(cookie)) + printk(KERN_ERR "%s:Failed to register for panel events\n", __func__); + else + printk(KERN_ERR "%s:panel_event_notifier_register register succeed\n", __func__); + } else if(retry_count > 0){ + printk(KERN_ERR "%s:active_panel is NULL Failed to register for panel events\n", __func__); + retry_count--; + schedule_delayed_work(&pvt_data ->panel_notify_register_work, msecs_to_jiffies(5000)); + + } +} + +static int charge_check_panel_sec(struct device_node *np) +{ + int i; + int count; + struct device_node *node; + struct drm_panel *panel; + + count = of_count_phandle_with_args(np, "panel_sec", NULL); + if (count <= 0) + return 0; + + for (i = 0; i < count; i++) { + node = of_parse_phandle(np, "panel_sec", i); + panel = of_drm_find_panel(node); + of_node_put(node); + if (!IS_ERR(panel)) { + active_panel_sec = panel; + return 0; + }else{ + active_panel_sec = NULL; + } + } + return PTR_ERR(panel); +} + +static void qti_battery_register_panel_sec_notifier_work(struct work_struct *work) +{ + struct device_node *node; + struct battery_chg_dev *pvt_data = container_of(work, struct battery_chg_dev, panel_sec_notify_register_work.work); + int error = 0; + static retry_count = 3; + + node = of_find_node_by_name(NULL, "charge-screen"); + if (!node) { + pr_err("%s ERROR: Cannot find node with panel!", __func__); + return; + } + + error = charge_check_panel_sec(node); + if (error == -EPROBE_DEFER) + pr_err("%s ERROR: Cannot fine panel of node!", __func__); + + if (active_panel_sec) { + cookie1 = panel_event_notifier_register(PANEL_EVENT_NOTIFICATION_SECONDARY, + PANEL_EVENT_NOTIFIER_CLIENT_CHARGE_SECOND, active_panel_sec, + screen_state_for_charge_callback, (void *)pvt_data); + pr_err("ERROR: cookie1:%s", cookie1); + if (IS_ERR(cookie1)) + printk(KERN_ERR "%s:Failed to register for second panel events\n", __func__); + else + printk(KERN_ERR "%s:panel_event_notifier_register second register succeed\n", __func__); + } else if(retry_count > 0){ + printk(KERN_ERR "%s:active_panel_sec is NULL Failed to register for panel events\n", __func__); + retry_count--; + schedule_delayed_work(&pvt_data ->panel_sec_notify_register_work, msecs_to_jiffies(5000)); + + } +} +#endif + +extern void generate_xm_charge_uvent(struct work_struct *work); +extern void xm_charger_debug_info_print_work(struct work_struct *work); +extern struct device_type dev_type_xiaomi_uevent; + +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; - rc = read_property_id(bcdev, pst, USB_CONNECTOR_TYPE); - if (rc < 0) { - pr_err("Failed to read prop USB_CONNECTOR_TYPE, rc=%d\n", - rc); - return 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 shutdown cmd to adsp: %d\n", rc); } - bcdev->connector_type = pst->prop[USB_CONNECTOR_TYPE]; - bcdev->usb_prev_mode = EXTCON_NONE; - - bcdev->extcon = devm_extcon_dev_allocate(bcdev->dev, - bcdev_usb_extcon_cable); - if (IS_ERR(bcdev->extcon)) { - rc = PTR_ERR(bcdev->extcon); - pr_err("Failed to allocate extcon device rc=%d\n", rc); - return rc; - } - - rc = devm_extcon_dev_register(bcdev->dev, bcdev->extcon); - if (rc < 0) { - pr_err("Failed to register extcon device rc=%d\n", rc); - return rc; - } - rc = extcon_set_property_capability(bcdev->extcon, EXTCON_USB, - EXTCON_PROP_USB_SS); - rc |= extcon_set_property_capability(bcdev->extcon, - EXTCON_USB_HOST, EXTCON_PROP_USB_SS); - if (rc < 0) - pr_err("failed to configure extcon capabilities rc=%d\n", rc); - else - pr_debug("Registered extcon, connector_type %s\n", - bcdev->connector_type ? "uusb" : "Typec"); - - return rc; + return NOTIFY_DONE; } static int battery_chg_probe(struct platform_device *pdev) @@ -2131,6 +2600,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 = @@ -2145,6 +2618,18 @@ static int battery_chg_probe(struct platform_device *pdev) 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_XM].version = + devm_kzalloc(&pdev->dev, MAX_STR_LEN, GFP_KERNEL); + mutex_init(&bcdev->rw_lock); init_rwsem(&bcdev->state_sem); init_completion(&bcdev->ack); @@ -2153,6 +2638,11 @@ static int battery_chg_probe(struct platform_device *pdev) 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->battery_check_work, battery_chg_check_status_work); + INIT_DELAYED_WORK(&bcdev->xm_prop_change_work, generate_xm_charge_uvent); + INIT_DELAYED_WORK(&bcdev->charger_debug_info_print_work, xm_charger_debug_info_print_work); +#if defined(CONFIG_BQ_FG_UPDATE) + INIT_DELAYED_WORK(&bcdev->batt_update_work, xm_batt_update_work); +#endif bcdev->dev = dev; rc = battery_chg_register_panel_notifier(bcdev); @@ -2188,6 +2678,11 @@ 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); + rc = battery_chg_parse_dt(bcdev); if (rc < 0) { dev_err(dev, "Failed to parse dt rc=%d\n", rc); @@ -2233,6 +2728,28 @@ 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->debug_work_en = 1; + + bcdev->shutdown_delay_en = true; + bcdev->slave_fg_verify_flag = false; + bcdev->battery_auth = false; + bcdev->slave_battery_auth = false; + bcdev->mtbf_current = 0; + dev->type = &dev_type_xiaomi_uevent; +#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) + INIT_WORK(&bcdev->notify_blankstate_work, notify_blankstate_changed_work); + INIT_DELAYED_WORK(&bcdev->panel_notify_register_work, qti_battery_register_panel_notifier_work); + schedule_delayed_work(&bcdev->panel_notify_register_work, msecs_to_jiffies(5000)); + if(bcdev->support_dual_panel) { + INIT_DELAYED_WORK(&bcdev->panel_sec_notify_register_work, qti_battery_register_panel_sec_notifier_work); + schedule_delayed_work(&bcdev->panel_sec_notify_register_work, msecs_to_jiffies(5000)); + } + pr_err("reading mi,support-dual-panel = %d\n", bcdev->support_dual_panel); +#endif +#if defined(CONFIG_BQ_FG_UPDATE) + schedule_delayed_work(&bcdev->batt_update_work, 0); +#endif return 0; error: @@ -2247,6 +2764,7 @@ static int battery_chg_probe(struct platform_device *pdev) cancel_work_sync(&bcdev->battery_check_work); complete(&bcdev->ack); unregister_reboot_notifier(&bcdev->reboot_notifier); + unregister_reboot_notifier(&bcdev->shutdown_notifier); reg_error: if (bcdev->notifier_cookie) panel_event_notifier_unregister(bcdev->notifier_cookie); @@ -2274,6 +2792,22 @@ static int battery_chg_remove(struct platform_device *pdev) cancel_work_sync(&bcdev->usb_type_work); cancel_work_sync(&bcdev->battery_check_work); unregister_reboot_notifier(&bcdev->reboot_notifier); + unregister_reboot_notifier(&bcdev->shutdown_notifier); + +#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) + if (active_panel && !IS_ERR(cookie)) { + panel_event_notifier_unregister(cookie); + } else { + printk(KERN_ERR "%s:main panel_event_notifier_unregister falt\n", __func__); + } + if(bcdev->support_dual_panel) { + if(active_panel_sec && !IS_ERR(cookie1)) { + panel_event_notifier_unregister(cookie1); + } else { + printk(KERN_ERR "%s:flip panel_event_notifier_unregister falt\n", __func__); + } + } +#endif return 0; } diff --git a/drivers/power/supply/qti_battery_charger.h b/drivers/power/supply/qti_battery_charger.h index fa8fddd781de..2c2f05c14a8f 100644 --- a/drivers/power/supply/qti_battery_charger.h +++ b/drivers/power/supply/qti_battery_charger.h @@ -20,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 @@ -28,6 +29,8 @@ #define BC_SHUTDOWN_NOTIFY 0x47 #define BC_HBOOST_VMAX_CLAMP_NOTIFY 0x79 #define BC_GENERIC_NOTIFY 0x80 +#define BC_XM_STATUS_GET 0x50 +#define BC_XM_STATUS_SET 0x51 /* Generic definitions */ #define MAX_STR_LEN 128 @@ -43,10 +46,34 @@ enum usb_connector_type { USB_CONNECTOR_TYPE_MICRO_USB, }; +#if defined(CONFIG_BQ_FG_2S) +#define BATTERY_DIGEST_LEN 20 +#else +#define BATTERY_DIGEST_LEN 32 +#endif +#define BATTERY_SS_AUTH_DATA_LEN 4 +#define USBPD_UVDM_SS_LEN 4 +#define USBPD_UVDM_VERIFIED_LEN 1 + +#define MAX_THERMAL_LEVEL 16 + +enum uvdm_state { + USBPD_UVDM_DISCONNECT, + USBPD_UVDM_CHARGER_VERSION, + USBPD_UVDM_CHARGER_VOLTAGE, + USBPD_UVDM_CHARGER_TEMP, + USBPD_UVDM_SESSION_SEED, + USBPD_UVDM_AUTHENTICATION, + USBPD_UVDM_VERIFIED, + USBPD_UVDM_REMOVE_COMPENSATION, + USBPD_UVDM_REVERSE_AUTHEN, + USBPD_UVDM_CONNECT, +}; enum psy_type { PSY_TYPE_BATTERY, PSY_TYPE_USB, PSY_TYPE_WLS, + PSY_TYPE_XM, PSY_TYPE_MAX, }; @@ -69,6 +96,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, @@ -115,10 +143,200 @@ enum wireless_property_id { 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, + XM_PROP_VBUS_DISABLE, + 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, + /*charger_pump sys node*/ + 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_MASTER_SMB1396_ONLINE, + XM_PROP_MASTER_SMB1396_IIN, + XM_PROP_SLAVE_SMB1396_ONLINE, + XM_PROP_SLAVE_SMB1396_IIN, + XM_PROP_SMB_IIN_DIFF, + XM_PROP_CC_ORIENTATION, + XM_PROP_INPUT_SUSPEND, + XM_PROP_FASTCHGMODE, + XM_PROP_NIGHT_CHARGING, + XM_PROP_SOC_DECIMAL, + XM_PROP_SOC_DECIMAL_RATE, + XM_PROP_QUICK_CHARGE_TYPE, + XM_PROP_APDO_MAX, + XM_PROP_DIE_TEMPERATURE, + XM_PROP_SLAVE_DIE_TEMPERATURE, + /* wireless charge infor */ + XM_PROP_WLS_START = 50, + 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_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_BIN, + XM_PROP_WLSCHARGE_CONTROL_LIMIT, + XM_PROP_FW_VER, + XM_PROP_WLS_THERMAL_REMOVE, + XM_PROP_WLS_DEBUG, + XM_PROP_WLS_FW_STATE, + XM_PROP_WLS_CAR_ADAPTER, + XM_PROP_WLS_TX_SPEED, + XM_PROP_WLS_FC_FLAG, + XM_PROP_WLS_END = 80, + /**********************/ + XM_PROP_SHUTDOWN_DELAY, + XM_PROP_FAKE_TEMP, + XM_PROP_THERMAL_REMOVE, + XM_PROP_TYPEC_MODE, + XM_PROP_MTBF_CURRENT, + XM_PROP_THERMAL_TEMP, + XM_PROP_FB_BLANK_STATE, + XM_PROP_SMART_BATT, + XM_PROP_SHIPMODE_COUNT_RESET, + XM_PROP_SPORT_MODE, + XM_PROP_BATT_CONNT_ONLINE, + XM_PROP_FAKE_CYCLE, + XM_PROP_FAKE_SOH, + /*********nvt fuelgauge feature*********/ + XM_PROP_NVTFG_MONITOR_ISC, + XM_PROP_NVTFG_MONITOR_SOA, + XM_PROP_OVER_PEAK_FLAG, + XM_PROP_CURRENT_DEVIATION, + XM_PROP_POWER_DEVIATION, + XM_PROP_AVERAGE_CURRENT, + XM_PROP_AVERAGE_TEMPERATURE, + XM_PROP_START_LEARNING, + XM_PROP_STOP_LEARNING, + XM_PROP_SET_LEARNING_POWER, + XM_PROP_GET_LEARNING_POWER, + XM_PROP_GET_LEARNING_POWER_DEV, + XM_PROP_GET_LEARNING_TIME_DEV, + XM_PROP_SET_CONSTANT_POWER, + XM_PROP_GET_REMAINING_TIME, + XM_PROP_SET_REFERANCE_POWER, + XM_PROP_GET_REFERANCE_CURRENT, + XM_PROP_GET_REFERANCE_POWER, + XM_PROP_START_LEARNING_B, + XM_PROP_STOP_LEARNING_B, + XM_PROP_SET_LEARNING_POWER_B, + XM_PROP_GET_LEARNING_POWER_B, + XM_PROP_GET_LEARNING_POWER_DEV_B, + /*********nvt fuelgauge feature*********/ + /*fuelgauge test node*/ + 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_FG1_RSOC, + XM_PROP_FG1_AI, + XM_PROP_FG1_CELL1_VOL, + XM_PROP_FG1_CELL2_VOL, + /* dual fuelgauge test node only for L18*/ + 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_FG1_ChargingStatus, + XM_PROP_FG1_GaugingStatus, + XM_PROP_FG1_FullChargeFlag, + 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_FG2_ChargingStatus, + XM_PROP_FG2_GaugingStatus, + XM_PROP_FG2_FullChargeFlag, + XM_PROP_FG2_RSOC, + XM_PROP_FG_VENDOR_ID, + /*begin dual fuel high temperature intercept feature */ + XM_PROP_FG_VOLTAGE_MAX, + XM_PROP_FG_Charge_Current_MAX, + XM_PROP_FG_Discharge_Current_MAX, + XM_PROP_FG_TEMP_MAX, + XM_PROP_FG_TEMP_MIN, + XM_PROP_FG_TIME_HT, + XM_PROP_FG_TIME_OT, + XM_PROP_FG_TIME_UT, + XM_PROP_FG_TIME_LT, + XM_PROP_FG_SEAL_SET, + XM_PROP_FG1_SEAL_STATE, + XM_PROP_FG1_DF_CHECK, + XM_PROP_FG2_SEAL_STATE, + XM_PROP_FG2_DF_CHECK, + /*end dual fuel high temperature intercept feature*/ +#if defined(CONFIG_BQ_CLOUD_AUTHENTICATION) + XM_PROP_SERVER_SN, + XM_PROP_SERVER_RESULT, + XM_PROP_ADSP_RESULT, +#endif + 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 { @@ -148,12 +366,34 @@ 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 - 32]; +}; + +struct wls_debug_msg { + struct pmic_glink_hdr hdr; + u32 property_id; + char data[MAX_STR_LEN]; +}; + struct battery_model_resp_msg { struct pmic_glink_hdr hdr; u32 property_id; char model[MAX_STR_LEN]; }; +struct xm_set_wls_bin_req_msg { + struct pmic_glink_hdr hdr; + u32 property_id; + u16 total_length; + u8 serial_number; + u8 fw_area; + u8 wls_fw_bin[MAX_STR_LEN]; +}; /* Message */ + struct wireless_fw_check_req { struct pmic_glink_hdr hdr; u32 fw_version; @@ -196,9 +436,28 @@ struct battery_charger_ship_mode_req_msg { u32 ship_mode_type; }; +struct xm_verify_digest_resp_msg { + struct pmic_glink_hdr hdr; + u32 property_id; + u8 digest[BATTERY_DIGEST_LEN]; + /*dual battery master and slave flag*/ + bool slave_fg; +}; + +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; @@ -224,22 +483,26 @@ struct battery_chg_dev { u32 *thermal_levels; const char *wls_fw_name; int curr_thermal_level; + int curr_wlsthermal_level; int num_thermal_levels; int shutdown_volt_mv; atomic_t state; struct work_struct subsys_up_work; struct work_struct usb_type_work; struct work_struct battery_check_work; + struct work_struct notify_blankstate_work; int fake_soc; bool block_tx; bool ship_mode_en; bool debug_battery_detected; bool wls_not_supported; bool wls_fw_update_reqd; + bool debug_work_en; u32 wls_fw_version; u16 wls_fw_crc; u32 wls_fw_update_time_ms; struct notifier_block reboot_notifier; + struct notifier_block shutdown_notifier; u32 thermal_fcc_ua; u32 restrict_fcc_ua; u32 last_fcc_ua; @@ -247,9 +510,36 @@ struct battery_chg_dev { u32 thermal_fcc_step; u32 connector_type; u32 usb_prev_mode; + u32 reverse_chg_flag; + u32 boost_mode; bool restrict_chg_en; + struct delayed_work xm_prop_change_work; + struct delayed_work charger_debug_info_print_work; +#if defined(CONFIG_BQ_FG_UPDATE) + struct delayed_work batt_update_work; +#endif + struct delayed_work panel_notify_register_work; + struct delayed_work panel_sec_notify_register_work; /* To track the driver initialization status */ bool initialized; bool notify_en; bool error_prop; + u8 *digest; + u32 *ss_auth_data; + char wls_debug_data[MAX_STR_LEN]; + /*shutdown delay is supported*/ + bool shutdown_delay_en; + bool support_2s_charging; + bool report_power_absent; + bool support_dual_panel; + /*dual battery authentic flag*/ + bool slave_fg_verify_flag; + + /*soc update flag*/ + bool support_soc_update; + + /*battery auth check for ssr*/ + bool battery_auth; + bool slave_battery_auth; + int mtbf_current; }; diff --git a/drivers/power/supply/qti_battery_charger_xiaomi.c b/drivers/power/supply/qti_battery_charger_xiaomi.c new file mode 100644 index 000000000000..36c016b9158f --- /dev/null +++ b/drivers/power/supply/qti_battery_charger_xiaomi.c @@ -0,0 +1,4248 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, The LineageOS Project. All rights reserved. + */ + +#define pr_fmt(fmt) "BATTERY_CHG: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include + +#include "qti_battery_charger.h" + +extern int battery_chg_write(struct battery_chg_dev *bcdev, void *data, + int len); +extern int write_property_id(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id, u32 val); +extern int read_property_id(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id); +extern int usb_psy_get_prop(struct power_supply *psy, + enum power_supply_property prop, + union power_supply_propval *pval); +extern const char *get_usb_type_name(u32 usb_type); +extern int get_property_id(struct psy_state *pst, + enum power_supply_property prop); +extern int wls_psy_get_prop(struct power_supply *psy, + enum power_supply_property prop, + union power_supply_propval *pval); + +extern const char *const power_supply_usb_type_text[]; + +static const char * const power_supply_usbc_text[] = { + "Nothing attached", + "Source attached (default current)", + "Source attached (medium current)", + "Source attached (high current)", + "Non compliant", + "Sink attached", + "Powered cable w/ sink", + "Debug Accessory", + "Audio Adapter", + "Powered cable w/o sink", +}; + +int StringToHex(char *str, unsigned char *out, unsigned int *outlen) +{ + char *p = str; + char high = 0, low = 0; + int tmplen = strlen(p), cnt = 0; + tmplen = strlen(p); + while(cnt < (tmplen / 2)) + { + high = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48; + low = (*(++ p) > '9' && ((*p <= 'F') || (*p <= 'f'))) ? *(p) - 48 - 7 : *(p) - 48; + out[cnt] = ((high & 0x0f) << 4 | (low & 0x0f)); + p ++; + cnt ++; + } + if(tmplen % 2 != 0) out[cnt] = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48; + + if(outlen != NULL) *outlen = tmplen / 2 + tmplen % 2; + + return tmplen / 2 + tmplen % 2; +} + +static int write_ss_auth_prop_id(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id, u32* buff) +{ + struct xm_ss_auth_resp_msg req_msg = { { 0 } }; + + req_msg.property_id = prop_id; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_set; + memcpy(req_msg.data, buff, BATTERY_SS_AUTH_DATA_LEN*sizeof(u32)); + + pr_debug("psy: prop_id:%d size:%d data[0]:0x%x data[1]:0x%x data[2]:0x%x data[3]:0x%x\n", + req_msg.property_id, sizeof(req_msg), req_msg.data[0], req_msg.data[1], req_msg.data[2], req_msg.data[3]); + + return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); +} + +static int read_ss_auth_property_id(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id) +{ + struct xm_ss_auth_resp_msg req_msg = { { 0 } }; + + req_msg.property_id = prop_id; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_get; + + pr_debug("psy: %s prop_id: %u\n", pst->psy->desc->name, + req_msg.property_id); + + return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); +} + +static int write_verify_digest_prop_id(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id, u8* buff) +{ + struct xm_verify_digest_resp_msg req_msg = { { 0 } }; + + req_msg.property_id = prop_id; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_set; + req_msg.slave_fg = bcdev->slave_fg_verify_flag; + memcpy(req_msg.digest, buff, BATTERY_DIGEST_LEN); + + pr_debug("psy: prop_id:%d size:%d\n", req_msg.property_id, sizeof(req_msg)); + + return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); +} + +static int read_verify_digest_property_id(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id) +{ + struct xm_verify_digest_resp_msg req_msg = { { 0 } }; + + req_msg.property_id = prop_id; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_get; + req_msg.slave_fg = bcdev->slave_fg_verify_flag; + pr_debug("psy: %s prop_id: %u\n", pst->psy->desc->name, + req_msg.property_id); + + return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); +} +static ssize_t verify_slave_flag_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + bcdev->slave_fg_verify_flag = val; + pr_err("verify_digest_flag :%d \n", val); + + return count; +} + +static ssize_t verify_slave_flag_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + + return scnprintf(buf, PAGE_SIZE, "%u\n", bcdev->slave_fg_verify_flag); +} +static CLASS_ATTR_RW(verify_slave_flag); + +#if defined(CONFIG_MI_WIRELESS) +static int write_wls_bin_prop_id(struct battery_chg_dev *bcdev, struct psy_state *pst, + u32 prop_id, u16 total_length, u8 serial_number, u8 fw_area, u8* buff) +{ + struct xm_set_wls_bin_req_msg req_msg = { { 0 } }; + + req_msg.property_id = prop_id; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_set; + req_msg.total_length = total_length; + req_msg.serial_number = serial_number; + req_msg.fw_area = fw_area; + if(serial_number < total_length/MAX_STR_LEN) + memcpy(req_msg.wls_fw_bin, buff, MAX_STR_LEN); + else if(serial_number == total_length/MAX_STR_LEN) + memcpy(req_msg.wls_fw_bin, buff, total_length - serial_number*MAX_STR_LEN); + + pr_debug("psy: prop_id:%d size:%d\n", req_msg.property_id, sizeof(req_msg)); + + return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); +} + +static int show_wls_fw_property_id(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id) +{ + struct wls_fw_resp_msg req_msg = { { 0 } }; + + req_msg.property_id = prop_id; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_get; + + pr_debug("psy: %s prop_id: %u\n", pst->psy->desc->name, + req_msg.property_id); + + return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); +} + +static int update_wls_fw_version(struct battery_chg_dev *bcdev, + struct psy_state *pst, u32 prop_id, u32 val) +{ + struct wls_fw_resp_msg req_msg = { { 0 } }; + + req_msg.property_id = prop_id; + req_msg.value = val; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_set; + + pr_debug("psy: %s prop_id: %u val: %u\n", pst->psy->desc->name, + req_msg.property_id, val); + + return battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); +} +#endif + +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; + +enum power_supply_quick_charge_type { + QUICK_CHARGE_NORMAL = 0, /* Charging Power <= 10W */ + QUICK_CHARGE_FAST, /* 10W < Charging Power <= 20W */ + QUICK_CHARGE_FLASH, /* 20W < Charging Power <= 30W */ + QUICK_CHARGE_TURBE, /* 30W < Charging Power <= 50W */ + QUICK_CHARGE_SUPER, /* Charging Power > 50W */ + QUICK_CHARGE_MAX, +}; + +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 ssize_t quick_charge_type_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY]; + int i = 0,verify_digiest = 0; + int rc; + u8 result = QUICK_CHARGE_NORMAL; + 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_HOT)) + result = QUICK_CHARGE_NORMAL; + else if (real_charger_type == POWER_SUPPLY_USB_TYPE_PD_PPS && verify_digiest ==1) { + if(apdo_max >= 50) { + result = QUICK_CHARGE_SUPER; + } + else + result = QUICK_CHARGE_TURBE; + } + else if (real_charger_type == POWER_SUPPLY_USB_TYPE_PD_PPS) + result = QUICK_CHARGE_FAST; + else { + while (adapter_cap[i].adap_type != 0) { + if (real_charger_type == adapter_cap[i].adap_type) { + result = adapter_cap[i].adap_cap; + } + i++; + } + } + +#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: + result = QUICK_CHARGE_FLASH; + break; + case ADAPTER_XIAOMI_PD_30W: + case ADAPTER_VOICE_BOX_30W: + case ADAPTER_XIAOMI_PD_50W: + case ADAPTER_XIAOMI_PD_60W: + case ADAPTER_XIAOMI_PD_100W: + result = QUICK_CHARGE_SUPER; + break; + default: + result = QUICK_CHARGE_NORMAL; + break; + } +#endif + + return scnprintf(buf, PAGE_SIZE, "%u", result); +} +static CLASS_ATTR_RO(quick_charge_type); + +#if defined(CONFIG_MI_WIRELESS) +static ssize_t wireless_chip_fw_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + u32 val; + + if (kstrtouint( buf, 10, &val)) + return -EINVAL; + + rc = update_wls_fw_version(bcdev, pst, XM_PROP_FW_VER, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t wireless_chip_fw_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = show_wls_fw_property_id(bcdev, pst, XM_PROP_FW_VER); + //rc = read_property_id(bcdev, pst, WLS_FW_VER); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%s\n", pst->version); +} +static CLASS_ATTR_RW(wireless_chip_fw); + +static ssize_t wls_debug_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + struct wls_debug_msg req_msg = { { 0 } }; + int rc; + + pr_info("buf: %s, count: %d ", buf, count); + + req_msg.property_id = XM_PROP_WLS_DEBUG; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_set; + + memset(req_msg.data, '\0', sizeof(req_msg.data)); + strncpy(req_msg.data, buf, count); + + rc = battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); + if (rc < 0) + return rc; + return count; +} + +static ssize_t wls_debug_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + struct wls_debug_msg req_msg = { { 0 } }; + int rc; + + req_msg.property_id = XM_PROP_WLS_DEBUG; + req_msg.hdr.owner = MSG_OWNER_BC; + req_msg.hdr.type = MSG_TYPE_REQ_RESP; + req_msg.hdr.opcode = pst->opcode_get; + + rc = battery_chg_write(bcdev, &req_msg, sizeof(req_msg)); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%s", bcdev->wls_debug_data); +} +static CLASS_ATTR_RW(wls_debug); + +static ssize_t wls_fw_state_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_WLS_FW_STATE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_WLS_FW_STATE]); +} +static CLASS_ATTR_RO(wls_fw_state); + +static ssize_t wls_car_adapter_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_WLS_CAR_ADAPTER); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_WLS_CAR_ADAPTER]); +} +static CLASS_ATTR_RO(wls_car_adapter); + +static ssize_t wls_fc_flag_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_WLS_FC_FLAG); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_WLS_FC_FLAG]); +} +static CLASS_ATTR_RO(wls_fc_flag); + +static ssize_t wls_tx_speed_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_WLS_TX_SPEED, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t wls_tx_speed_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_WLS_TX_SPEED); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_WLS_TX_SPEED]); +} +static CLASS_ATTR_RW(wls_tx_speed); +#endif + +static ssize_t real_type_show(struct class *c, struct class_attribute *attr, + char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_REAL_TYPE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%s\n", + get_usb_type_name(pst->prop[XM_PROP_REAL_TYPE])); +} +static CLASS_ATTR_RO(real_type); + +static ssize_t resistance_id_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_RESISTANCE_ID); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_RESISTANCE_ID]); +} +static CLASS_ATTR_RO(resistance_id); + +static ssize_t verify_digest_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + u8 random_1s[BATTERY_DIGEST_LEN + 1] = {0}; + char kbuf_1s[70] = {0}; + u8 random_2s[BATTERY_DIGEST_LEN + 1] = {0}; + char kbuf_2s[2 * BATTERY_DIGEST_LEN + 1] = {0}; + int rc; + int i; + + if (bcdev->support_2s_charging) { + memset(kbuf_2s, 0, sizeof(kbuf_2s)); + strlcpy(kbuf_2s, buf, 2 * BATTERY_DIGEST_LEN + 1); + StringToHex(kbuf_2s, random_2s, &i); + //pr_err("verify_digest_store 2s:%s \n", random_2s); + rc = write_verify_digest_prop_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_VERIFY_DIGEST, random_2s); + } else { + memset(kbuf_1s, 0, sizeof(kbuf_1s)); + strncpy(kbuf_1s, buf, count - 1); + StringToHex(kbuf_1s, random_1s, &i); + //pr_err("verify_digest_store 1s:%s \n", random_1s); + rc = write_verify_digest_prop_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_VERIFY_DIGEST, random_1s); + } + if (rc < 0) + return rc; + + return count; +} + +static ssize_t verify_digest_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + u8 digest_buf[4]; + int i; + int len; + + rc = read_verify_digest_property_id(bcdev, pst, XM_PROP_VERIFY_DIGEST); + if (rc < 0) + return rc; + + for (i = 0; i < BATTERY_DIGEST_LEN; i++) { + memset(digest_buf, 0, sizeof(digest_buf)); + snprintf(digest_buf, sizeof(digest_buf) - 1, "%02x", bcdev->digest[i]); + strlcat(buf, digest_buf, BATTERY_DIGEST_LEN * 2 + 1); + } + len = strlen(buf); + buf[len] = '\0'; + pr_err("verify_digest_show :%s \n", buf); + return strlen(buf) + 1; +} +static CLASS_ATTR_RW(verify_digest); + +#if defined(CONFIG_MI_WIRELESS) +static ssize_t wls_bin_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc, retry, tmp_serial; + static u16 total_length = 0; + static u8 serial_number = 0; + static u8 fw_area = 0; + int i; + + pr_err("buf:%s, count:%d\n", buf, count); + if( strncmp("length:", buf, 7 ) == 0 ) { + if (kstrtou16( buf+7, 10, &total_length)) + return -EINVAL; + serial_number = 0; + pr_err("total_length:%d, serial_number:%d\n", total_length, serial_number); + } else if( strncmp("area:", buf, 5 ) == 0 ) { + if (kstrtou8( buf+5, 10, &fw_area)) + return -EINVAL; + pr_err("area:%d\n", fw_area); + }else { + for(i=0; i < count; ++i ) + pr_err("wls_bin_data[%d]=%x\n",serial_number*MAX_STR_LEN+i,buf[i]); + + for( tmp_serial=0; + (tmp_serial<(count+MAX_STR_LEN-1)/MAX_STR_LEN) && (serial_number<(total_length+MAX_STR_LEN-1)/MAX_STR_LEN); + ++tmp_serial,++serial_number) + { + for(retry = 0; retry < 3; ++retry ) + { + rc = write_wls_bin_prop_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_WLS_BIN, + total_length, + serial_number, + fw_area, + (u8 *)buf+tmp_serial*MAX_STR_LEN); + pr_err("total_length:%d, serial_number:%d, retry:%d\n", total_length, serial_number, retry); + if (rc == 0) + break; + } + } + } + return count; +} +static CLASS_ATTR_WO(wls_bin); +#endif + +static ssize_t connector_temp_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_CONNECTOR_TEMP, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t connector_temp_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_CONNECTOR_TEMP); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_CONNECTOR_TEMP]); +} +static CLASS_ATTR_RW(connector_temp); + +static ssize_t authentic_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + bcdev->battery_auth = val; + pr_err("authentic_store: %d\n", val); + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_AUTHENTIC, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t authentic_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_AUTHENTIC); + if (rc < 0) + return rc; + + pr_err("authentic_show: %d\n", pst->prop[XM_PROP_AUTHENTIC]); + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_AUTHENTIC]); +} +static CLASS_ATTR_RW(authentic); + +static ssize_t chip_ok_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_CHIP_OK); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_CHIP_OK]); +} +static CLASS_ATTR_RO(chip_ok); + + +static ssize_t vbus_disable_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_VBUS_DISABLE, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t vbus_disable_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_VBUS_DISABLE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_VBUS_DISABLE]); +} +static CLASS_ATTR_RW(vbus_disable); + + +#if defined(CONFIG_MI_WIRELESS) +static ssize_t tx_mac_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + u64 value = 0; + + rc = read_property_id(bcdev, pst, XM_PROP_TX_MACL); + if (rc < 0) + return rc; + + rc = read_property_id(bcdev, pst, XM_PROP_TX_MACH); + if (rc < 0) + return rc; + value = pst->prop[XM_PROP_TX_MACH]; + value = (value << 32) + pst->prop[XM_PROP_TX_MACL]; + + return scnprintf(buf, PAGE_SIZE, "%llx", value); +} +static CLASS_ATTR_RO(tx_mac); + +static ssize_t rx_cr_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + u64 value = 0; + rc = read_property_id(bcdev, pst, XM_PROP_RX_CRL); + if (rc < 0) + return rc; + + rc = read_property_id(bcdev, pst, XM_PROP_RX_CRH); + if (rc < 0) + return rc; + value = pst->prop[XM_PROP_RX_CRH]; + value = (value << 32) + pst->prop[XM_PROP_RX_CRL]; + + return scnprintf(buf, PAGE_SIZE, "%llx", value); +} +static CLASS_ATTR_RO(rx_cr); + +static ssize_t rx_cep_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_RX_CEP); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%x", pst->prop[XM_PROP_RX_CEP]); +} +static CLASS_ATTR_RO(rx_cep); + +static ssize_t bt_state_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_BT_STATE, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t bt_state_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BT_STATE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_BT_STATE]); +} +static CLASS_ATTR_RW(bt_state); + +static ssize_t wlscharge_control_limit_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + if(val == bcdev->curr_wlsthermal_level) + return count; + + pr_err("set thermal-level: %d num_thermal_levels: %d \n", val, bcdev->num_thermal_levels); + + if (bcdev->num_thermal_levels <= 0) { + pr_err("Incorrect num_thermal_levels\n"); + return -EINVAL; + } + + if (val < 0 || val >= bcdev->num_thermal_levels) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_WLSCHARGE_CONTROL_LIMIT, val); + if (rc < 0) + return rc; + + bcdev->curr_wlsthermal_level = val; + + return count; +} + +static ssize_t wlscharge_control_limit_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_WLSCHARGE_CONTROL_LIMIT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_WLSCHARGE_CONTROL_LIMIT]); +} +static CLASS_ATTR_RW(wlscharge_control_limit); + +static ssize_t reverse_chg_mode_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + bcdev->boost_mode = val; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_REVERSE_CHG_MODE, val); + if (rc < 0) + return rc; + return count; +} + +static ssize_t reverse_chg_mode_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_REVERSE_CHG_MODE); + if (rc < 0) + goto out; + + if (bcdev->reverse_chg_flag != pst->prop[XM_PROP_REVERSE_CHG_MODE]) { + if (pst->prop[XM_PROP_REVERSE_CHG_MODE]) { + pm_stay_awake(bcdev->dev); + dev_info(bcdev->dev, "reverse chg add lock\n"); + } + else { + pm_relax(bcdev->dev); + dev_info(bcdev->dev, "reverse chg release lock\n"); + } + bcdev->reverse_chg_flag = pst->prop[XM_PROP_REVERSE_CHG_MODE]; + } + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_REVERSE_CHG_MODE]); + +out: + dev_err(bcdev->dev, "read reverse chg mode error\n"); + bcdev->reverse_chg_flag = 0; + pm_relax(bcdev->dev); + return rc; +} +static CLASS_ATTR_RW(reverse_chg_mode); + +static ssize_t reverse_chg_state_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_REVERSE_CHG_STATE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_REVERSE_CHG_STATE]); +} +static CLASS_ATTR_RO(reverse_chg_state); + +static ssize_t rx_vout_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_RX_VOUT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_RX_VOUT]); +} +static CLASS_ATTR_RO(rx_vout); + +static ssize_t rx_vrect_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_RX_VRECT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_RX_VRECT]); +} +static CLASS_ATTR_RO(rx_vrect); + +static ssize_t rx_iout_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_RX_IOUT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_RX_IOUT]); +} +static CLASS_ATTR_RO(rx_iout); + +static ssize_t tx_adapter_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_TX_ADAPTER); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_TX_ADAPTER]); +} +static CLASS_ATTR_RO(tx_adapter); + +static ssize_t op_mode_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_OP_MODE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_OP_MODE]); +} +static CLASS_ATTR_RO(op_mode); + + +static ssize_t wls_die_temp_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_WLS_DIE_TEMP); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_WLS_DIE_TEMP]); +} +static CLASS_ATTR_RO(wls_die_temp); + +static ssize_t wls_thermal_remove_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_WLS_THERMAL_REMOVE, val); + if (rc < 0) + return rc; + return count; +} + +static ssize_t wls_thermal_remove_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_WLS_THERMAL_REMOVE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_WLS_THERMAL_REMOVE]); +} +static CLASS_ATTR_RW(wls_thermal_remove); +#endif + +static ssize_t verify_process_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_VERIFY_PROCESS, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t verify_process_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_VERIFY_PROCESS); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_VERIFY_PROCESS]); +} +static CLASS_ATTR_RW(verify_process); + +static ssize_t soc_decimal_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SOC_DECIMAL); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_SOC_DECIMAL]); +} +static CLASS_ATTR_RO(soc_decimal); + +static ssize_t soc_decimal_rate_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SOC_DECIMAL_RATE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_SOC_DECIMAL_RATE]); +} +static CLASS_ATTR_RO(soc_decimal_rate); + +static ssize_t smart_batt_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 0, &val)) + return -EINVAL; + + pr_err("set smart batt charging %d\n", val); + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SMART_BATT, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t smart_batt_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SMART_BATT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SMART_BATT]); +} +static CLASS_ATTR_RW(smart_batt); + +#define BSWAP_32(x) \ + (u32)((((u32)(x) & 0xff000000) >> 24) | \ + (((u32)(x) & 0x00ff0000) >> 8) | \ + (((u32)(x) & 0x0000ff00) << 8) | \ + (((u32)(x) & 0x000000ff) << 24)) + +static void usbpd_sha256_bitswap32(unsigned int *array, int len) +{ + int i; + + for (i = 0; i < len; i++) { + array[i] = BSWAP_32(array[i]); + } +} + + +static void usbpd_request_vdm_cmd(struct battery_chg_dev *bcdev, enum uvdm_state cmd, unsigned int *data) +{ + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + u32 prop_id, val = 0; + int rc; + + pr_err("usbpd_request_vdm_cmd:cmd = %d, data = %d\n", cmd, *data); + switch (cmd) { + case USBPD_UVDM_CHARGER_VERSION: + prop_id = XM_PROP_VDM_CMD_CHARGER_VERSION; + break; + case USBPD_UVDM_CHARGER_VOLTAGE: + prop_id = XM_PROP_VDM_CMD_CHARGER_VOLTAGE; + break; + case USBPD_UVDM_CHARGER_TEMP: + prop_id = XM_PROP_VDM_CMD_CHARGER_TEMP; + break; + case USBPD_UVDM_SESSION_SEED: + prop_id = XM_PROP_VDM_CMD_SESSION_SEED; + usbpd_sha256_bitswap32(data, USBPD_UVDM_SS_LEN); + val = *data; + pr_err("SESSION_SEED:data = %d\n", val); + break; + case USBPD_UVDM_AUTHENTICATION: + prop_id = XM_PROP_VDM_CMD_AUTHENTICATION; + usbpd_sha256_bitswap32(data, USBPD_UVDM_SS_LEN); + val = *data; + pr_err("AUTHENTICATION:data = %d\n", val); + break; + case USBPD_UVDM_REVERSE_AUTHEN: + prop_id = XM_PROP_VDM_CMD_REVERSE_AUTHEN; + usbpd_sha256_bitswap32(data, USBPD_UVDM_SS_LEN); + val = *data; + pr_err("AUTHENTICATION:data = %d\n", val); + break; + case USBPD_UVDM_REMOVE_COMPENSATION: + prop_id = XM_PROP_VDM_CMD_REMOVE_COMPENSATION; + val = *data; + break; + case USBPD_UVDM_VERIFIED: + prop_id = XM_PROP_VDM_CMD_VERIFIED; + val = *data; + break; + default: + prop_id = XM_PROP_VDM_CMD_CHARGER_VERSION; + pr_info("cmd:%d is not support\n", cmd); + break; + } + + if(cmd == USBPD_UVDM_SESSION_SEED || cmd == USBPD_UVDM_AUTHENTICATION || cmd == USBPD_UVDM_REVERSE_AUTHEN) { + rc = write_ss_auth_prop_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + prop_id, data); + } + else + rc = write_property_id(bcdev, pst, prop_id, val); +} + +static ssize_t request_vdm_cmd_store(struct class *c, + struct class_attribute *attr, const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int cmd, ret; + unsigned char buffer[64]; + unsigned char data[32]; + int ccount; + + ret = sscanf(buf, "%d,%s\n", &cmd, buffer); + + pr_info("%s:buf:%s cmd:%d, buffer:%s\n", __func__, buf, cmd, buffer); + + StringToHex(buffer, data, &ccount); + usbpd_request_vdm_cmd(bcdev, cmd, (unsigned int *)data); + return count; +} + +static ssize_t request_vdm_cmd_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + u32 prop_id = 0; + int i; + char data[16], str_buf[128] = {0}; + enum uvdm_state cmd; + + rc = read_property_id(bcdev, pst, XM_PROP_UVDM_STATE); + if (rc < 0) + return rc; + + cmd = pst->prop[XM_PROP_UVDM_STATE]; + pr_info("request_vdm_cmd_show uvdm_state: %d\n", cmd); + + switch (cmd){ + case USBPD_UVDM_CHARGER_VERSION: + prop_id = XM_PROP_VDM_CMD_CHARGER_VERSION; + rc = read_property_id(bcdev, pst, prop_id); + return snprintf(buf, PAGE_SIZE, "%d,%d", cmd, pst->prop[prop_id]); + break; + case USBPD_UVDM_CHARGER_TEMP: + prop_id = XM_PROP_VDM_CMD_CHARGER_TEMP; + rc = read_property_id(bcdev, pst, prop_id); + return snprintf(buf, PAGE_SIZE, "%d,%d", cmd, pst->prop[prop_id]); + break; + case USBPD_UVDM_CHARGER_VOLTAGE: + prop_id = XM_PROP_VDM_CMD_CHARGER_VOLTAGE; + rc = read_property_id(bcdev, pst, prop_id); + return snprintf(buf, PAGE_SIZE, "%d,%d", cmd, pst->prop[prop_id]); + break; + case USBPD_UVDM_CONNECT: + case USBPD_UVDM_DISCONNECT: + case USBPD_UVDM_SESSION_SEED: + case USBPD_UVDM_VERIFIED: + case USBPD_UVDM_REMOVE_COMPENSATION: + case USBPD_UVDM_REVERSE_AUTHEN: + return snprintf(buf, PAGE_SIZE, "%d,Null", cmd); + break; + case USBPD_UVDM_AUTHENTICATION: + prop_id = XM_PROP_VDM_CMD_AUTHENTICATION; + rc = read_ss_auth_property_id(bcdev, pst, prop_id); + if (rc < 0) + return rc; + pr_info("auth:0x%x 0x%x 0x%x 0x%x\n", + bcdev->ss_auth_data[0],bcdev->ss_auth_data[1],bcdev->ss_auth_data[2],bcdev->ss_auth_data[3]); + for (i = 0; i < USBPD_UVDM_SS_LEN; i++) { + memset(data, 0, sizeof(data)); + snprintf(data, sizeof(data), "%08lx", bcdev->ss_auth_data[i]); + strlcat(str_buf, data, sizeof(str_buf)); + } + return snprintf(buf, PAGE_SIZE, "%d,%s", cmd, str_buf); + break; + default: + pr_info("feedbak cmd:%d is not support\n", cmd); + break; + } + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[prop_id]); +} +static CLASS_ATTR_RW(request_vdm_cmd); + +static const char * const usbpd_state_strings[] = { + "UNKNOWN", + "SNK_Startup", + "SNK_Ready", + "SRC_Ready", +}; + +static ssize_t current_state_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_CURRENT_STATE); + if (rc < 0) + return rc; + if (pst->prop[XM_PROP_CURRENT_STATE] == 25) + return snprintf(buf, PAGE_SIZE, "%s", usbpd_state_strings[1]); + else if (pst->prop[XM_PROP_CURRENT_STATE] == 31) + return snprintf(buf, PAGE_SIZE, "%s", usbpd_state_strings[2]); + else if (pst->prop[XM_PROP_CURRENT_STATE] == 5) + return snprintf(buf, PAGE_SIZE, "%s", usbpd_state_strings[3]); + else + return snprintf(buf, PAGE_SIZE, "%s", usbpd_state_strings[0]); + +} +static CLASS_ATTR_RO(current_state); + +static ssize_t adapter_id_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_ADAPTER_ID); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%08x", pst->prop[XM_PROP_ADAPTER_ID]); +} +static CLASS_ATTR_RO(adapter_id); + +static ssize_t adapter_svid_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_ADAPTER_SVID); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%04x", pst->prop[XM_PROP_ADAPTER_SVID]); +} +static CLASS_ATTR_RO(adapter_svid); + +static ssize_t pd_verifed_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_PD_VERIFED, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t pd_verifed_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_PD_VERIFED); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_PD_VERIFED]); +} +static CLASS_ATTR_RW(pd_verifed); + +static ssize_t pdo2_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_PDO2); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%08x\n", pst->prop[XM_PROP_PDO2]); +} +static CLASS_ATTR_RO(pdo2); + +static ssize_t bq2597x_chip_ok_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_CHIP_OK); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_CHIP_OK]); +} +static CLASS_ATTR_RO(bq2597x_chip_ok); + +static ssize_t bq2597x_slave_chip_ok_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_SLAVE_CHIP_OK); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_SLAVE_CHIP_OK]); +} +static CLASS_ATTR_RO(bq2597x_slave_chip_ok); + +static ssize_t bq2597x_bus_current_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_BUS_CURRENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_BUS_CURRENT]); +} +static CLASS_ATTR_RO(bq2597x_bus_current); + +static ssize_t bq2597x_slave_bus_current_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_SLAVE_BUS_CURRENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_SLAVE_BUS_CURRENT]); +} +static CLASS_ATTR_RO(bq2597x_slave_bus_current); + +static ssize_t bq2597x_bus_delta_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_BUS_DELTA); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_BUS_DELTA]); +} +static CLASS_ATTR_RO(bq2597x_bus_delta); + +static ssize_t bq2597x_bus_voltage_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_BUS_VOLTAGE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_BUS_VOLTAGE]); +} +static CLASS_ATTR_RO(bq2597x_bus_voltage); + +static ssize_t bq2597x_battery_present_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_BATTERY_PRESENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_BATTERY_PRESENT]); +} +static CLASS_ATTR_RO(bq2597x_battery_present); + +static ssize_t bq2597x_slave_battery_present_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_SLAVE_BATTERY_PRESENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_SLAVE_BATTERY_PRESENT]); +} +static CLASS_ATTR_RO(bq2597x_slave_battery_present); +static ssize_t bq2597x_battery_voltage_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BQ2597X_BATTERY_VOLTAGE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_BQ2597X_BATTERY_VOLTAGE]); +} +static CLASS_ATTR_RO(bq2597x_battery_voltage); + +static ssize_t master_smb1396_online_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_MASTER_SMB1396_ONLINE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_MASTER_SMB1396_ONLINE]); +} +static CLASS_ATTR_RO(master_smb1396_online); + +static ssize_t master_smb1396_iin_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_MASTER_SMB1396_IIN); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_MASTER_SMB1396_IIN]); +} +static CLASS_ATTR_RO(master_smb1396_iin); + + +static ssize_t slave_smb1396_online_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SLAVE_SMB1396_ONLINE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SLAVE_SMB1396_ONLINE]); +} +static CLASS_ATTR_RO(slave_smb1396_online); + +static ssize_t slave_smb1396_iin_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SLAVE_SMB1396_IIN); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SLAVE_SMB1396_IIN]); +} +static CLASS_ATTR_RO(slave_smb1396_iin); + +static ssize_t smb_iin_diff_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SMB_IIN_DIFF); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SMB_IIN_DIFF]); +} +static CLASS_ATTR_RO(smb_iin_diff); + +static ssize_t cc_orientation_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_CC_ORIENTATION); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_CC_ORIENTATION]); +} +static CLASS_ATTR_RO(cc_orientation); + +static ssize_t input_suspend_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + pr_err("set charger input suspend %d\n", val); + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_INPUT_SUSPEND, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t input_suspend_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_INPUT_SUSPEND); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_INPUT_SUSPEND]); +} +static CLASS_ATTR_RW(input_suspend); + +static ssize_t fastchg_mode_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FASTCHGMODE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FASTCHGMODE]); +} +static CLASS_ATTR_RO(fastchg_mode); + +static ssize_t apdo_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_APDO_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_APDO_MAX]); +} +static CLASS_ATTR_RO(apdo_max); + +static ssize_t die_temperature_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_DIE_TEMPERATURE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_DIE_TEMPERATURE]); +} +static CLASS_ATTR_RO(die_temperature); + +static ssize_t slave_die_temperature_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SLAVE_DIE_TEMPERATURE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SLAVE_DIE_TEMPERATURE]); +} +static CLASS_ATTR_RO(slave_die_temperature); + +static ssize_t night_charging_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + bool val; + if (kstrtobool(buf, &val)) + return -EINVAL; + pr_err("set charger night charging %d\n", val); + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_NIGHT_CHARGING, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t night_charging_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_NIGHT_CHARGING); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_NIGHT_CHARGING]); +} +static CLASS_ATTR_RW(night_charging); + +static ssize_t fake_temp_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_FAKE_TEMP, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t fake_temp_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FAKE_TEMP); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FAKE_TEMP]); +} +static CLASS_ATTR_RW(fake_temp); + + +static ssize_t shutdown_delay_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SHUTDOWN_DELAY); + if (rc < 0) + return rc; + + if (!bcdev->shutdown_delay_en) + pst->prop[XM_PROP_SHUTDOWN_DELAY] = 0; + + return scnprintf(buf, PAGE_SIZE, "%u", pst->prop[XM_PROP_SHUTDOWN_DELAY]); +} + +static ssize_t shutdown_delay_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + bcdev->shutdown_delay_en = val; + pr_err("use contral shutdown delay featue enable= %d\n", bcdev->shutdown_delay_en); + + return count; +} + +static CLASS_ATTR_RW(shutdown_delay); + + +static ssize_t thermal_remove_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_THERMAL_REMOVE, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t thermal_remove_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_THERMAL_REMOVE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_THERMAL_REMOVE]); +} +static CLASS_ATTR_RW(thermal_remove); + +static ssize_t typec_mode_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_TYPEC_MODE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%s\n", power_supply_usbc_text[pst->prop[XM_PROP_TYPEC_MODE]]); +} +static CLASS_ATTR_RO(typec_mode); + +static ssize_t mtbf_current_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + bcdev->mtbf_current = val; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_MTBF_CURRENT, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t mtbf_current_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_MTBF_CURRENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_MTBF_CURRENT]); +} +static CLASS_ATTR_RW(mtbf_current); + +/* fuelgauge test node */ +static ssize_t fg1_qmax_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_QMAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_QMAX]); +} +static CLASS_ATTR_RO(fg1_qmax); +static ssize_t fg1_rm_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_RM); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_RM]); +} +static CLASS_ATTR_RO(fg1_rm); +static ssize_t fg1_fcc_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_FCC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_FCC]); +} +static CLASS_ATTR_RO(fg1_fcc); + +static ssize_t fg1_soh_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_SOH); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_SOH]); +} +static CLASS_ATTR_RO(fg1_soh); + +static ssize_t fg1_rsoc_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_RSOC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_RSOC]); +} +static CLASS_ATTR_RO(fg1_rsoc); + +static ssize_t fg1_ai_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_AI); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_AI]); +} +static CLASS_ATTR_RO(fg1_ai); + +static ssize_t fg1_fcc_soh_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_FCC_SOH); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_FCC_SOH]); +} +static CLASS_ATTR_RO(fg1_fcc_soh); +static ssize_t fg1_cycle_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_CYCLE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_CYCLE]); +} +static CLASS_ATTR_RO(fg1_cycle); + +static ssize_t fake_cycle_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_FAKE_CYCLE, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t fake_soh_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_FAKE_SOH, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t fake_soh_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FAKE_SOH); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FAKE_SOH]); +} +static CLASS_ATTR_RW(fake_soh); + +static ssize_t fake_cycle_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FAKE_CYCLE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FAKE_CYCLE]); +} +static CLASS_ATTR_RW(fake_cycle); + +static ssize_t fg1_fastcharge_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_FAST_CHARGE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_FAST_CHARGE]); +} +static CLASS_ATTR_RO(fg1_fastcharge); + +static ssize_t fg1_current_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_CURRENT_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_CURRENT_MAX]); +} +static CLASS_ATTR_RO(fg1_current_max); + +static ssize_t fg1_vol_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_VOL_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_VOL_MAX]); +} +static CLASS_ATTR_RO(fg1_vol_max); + +static ssize_t fg1_tsim_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_TSIM); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_TSIM]); +} +static CLASS_ATTR_RO(fg1_tsim); + +static ssize_t fg1_tambient_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_TAMBIENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_TAMBIENT]); +} +static CLASS_ATTR_RO(fg1_tambient); + +static ssize_t fg1_tremq_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_TREMQ); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_TREMQ]); +} +static CLASS_ATTR_RO(fg1_tremq); + +static ssize_t fg1_tfullq_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_TFULLQ); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_TFULLQ]); +} +static CLASS_ATTR_RO(fg1_tfullq); +#if defined(CONFIG_BQ_CLOUD_AUTHENTICATION) +static ssize_t server_sn_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + int test[8] = {0}; + int i = 0; + + for(i = 0; i < 8; i++) + { + rc = read_property_id(bcdev, pst, XM_PROP_SERVER_SN); + if (rc < 0) + return rc; + test[i] = pst->prop[XM_PROP_SERVER_SN]; + } + return scnprintf(buf, PAGE_SIZE, "0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x\n", + (test[0]>>24)&0xff, (test[0]>>16)&0xff, (test[0]>>8)&0xff, (test[0]>>0)&0xff, + (test[1]>>24)&0xff, (test[1]>>16)&0xff, (test[1]>>8)&0xff, (test[1]>>0)&0xff, + (test[2]>>24)&0xff, (test[2]>>16)&0xff, (test[2]>>8)&0xff, (test[2]>>0)&0xff, + (test[3]>>24)&0xff, (test[3]>>16)&0xff, (test[3]>>8)&0xff, (test[3]>>0)&0xff, + (test[4]>>24)&0xff, (test[4]>>16)&0xff, (test[4]>>8)&0xff, (test[4]>>0)&0xff, + (test[5]>>24)&0xff, (test[5]>>16)&0xff, (test[5]>>8)&0xff, (test[5]>>0)&0xff, + (test[6]>>24)&0xff, (test[6]>>16)&0xff, (test[6]>>8)&0xff, (test[6]>>0)&0xff, + (test[7]>>24)&0xff, (test[7]>>16)&0xff, (test[7]>>8)&0xff, (test[7]>>0)&0xff); +} +static CLASS_ATTR_RO(server_sn); +static ssize_t server_result_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + bool val; + int rc; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + rc = write_property_id(bcdev, pst, XM_PROP_SERVER_RESULT, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t server_result_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SERVER_RESULT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_SERVER_RESULT]); +} +static CLASS_ATTR_RW(server_result); +static ssize_t adsp_result_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_ADSP_RESULT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_ADSP_RESULT]); +} +static CLASS_ATTR_RO(adsp_result); +#endif + +static ssize_t fg_vendor_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_VENDOR_ID); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_VENDOR_ID]); +} +static CLASS_ATTR_RO(fg_vendor); + +static ssize_t battcont_online_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_BATT_CONNT_ONLINE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_BATT_CONNT_ONLINE]); +} +static CLASS_ATTR_RO(battcont_online); + +static ssize_t battmoni_isc_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_NVTFG_MONITOR_ISC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_NVTFG_MONITOR_ISC]); +} +static CLASS_ATTR_RO(battmoni_isc); + +static ssize_t battmoni_soa_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_NVTFG_MONITOR_SOA); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_NVTFG_MONITOR_SOA]); +} +static CLASS_ATTR_RO(battmoni_soa); + +static ssize_t over_peak_flag_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_OVER_PEAK_FLAG); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_OVER_PEAK_FLAG]); +} +static CLASS_ATTR_RO(over_peak_flag); + +static ssize_t current_deviation_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_CURRENT_DEVIATION); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_CURRENT_DEVIATION]); +} +static CLASS_ATTR_RO(current_deviation); + +static ssize_t power_deviation_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_POWER_DEVIATION); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_POWER_DEVIATION]); +} +static CLASS_ATTR_RO(power_deviation); + +static ssize_t average_current_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_AVERAGE_CURRENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_AVERAGE_CURRENT]); +} +static CLASS_ATTR_RO(average_current); + +static ssize_t average_temp_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_AVERAGE_TEMPERATURE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_AVERAGE_TEMPERATURE]); +} +static CLASS_ATTR_RO(average_temp); + +static ssize_t start_learn_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_START_LEARNING, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t start_learn_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_START_LEARNING); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_START_LEARNING]); +} +static CLASS_ATTR_RW(start_learn); + +static ssize_t stop_learn_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_STOP_LEARNING, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t stop_learn_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_STOP_LEARNING); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_STOP_LEARNING]); +} +static CLASS_ATTR_RW(stop_learn); + +static ssize_t set_learn_power_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SET_LEARNING_POWER, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t set_learn_power_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_SET_LEARNING_POWER); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_SET_LEARNING_POWER]); +} +static CLASS_ATTR_RW(set_learn_power); + +static ssize_t get_learn_power_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_LEARNING_POWER); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_LEARNING_POWER]); +} +static CLASS_ATTR_RO(get_learn_power); + +static ssize_t get_learn_power_dev_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_LEARNING_POWER_DEV); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_LEARNING_POWER_DEV]); +} +static CLASS_ATTR_RO(get_learn_power_dev); + +static ssize_t start_learn_b_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_START_LEARNING_B, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t start_learn_b_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_START_LEARNING_B); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_START_LEARNING_B]); +} +static CLASS_ATTR_RW(start_learn_b); + +static ssize_t stop_learn_b_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_STOP_LEARNING_B, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t stop_learn_b_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_STOP_LEARNING_B); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_STOP_LEARNING_B]); +} +static CLASS_ATTR_RW(stop_learn_b); + +static ssize_t set_learn_power_b_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SET_LEARNING_POWER_B, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t set_learn_power_b_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_SET_LEARNING_POWER_B); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_SET_LEARNING_POWER_B]); +} +static CLASS_ATTR_RW(set_learn_power_b); + +static ssize_t get_learn_power_b_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_LEARNING_POWER_B); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_LEARNING_POWER_B]); +} +static CLASS_ATTR_RO(get_learn_power_b); + +static ssize_t get_learn_power_dev_b_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_LEARNING_POWER_DEV_B); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_LEARNING_POWER_DEV_B]); +} +static CLASS_ATTR_RO(get_learn_power_dev_b); + +static ssize_t get_learn_time_dev_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_LEARNING_TIME_DEV); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_LEARNING_TIME_DEV]); +} +static CLASS_ATTR_RO(get_learn_time_dev); + +static ssize_t constant_power_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SET_CONSTANT_POWER, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t constant_power_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_SET_CONSTANT_POWER); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_SET_CONSTANT_POWER]); +} +static CLASS_ATTR_RW(constant_power); + +static ssize_t remaining_time_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_REMAINING_TIME); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_REMAINING_TIME]); +} +static CLASS_ATTR_RO(remaining_time); + +static ssize_t referance_power_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SET_REFERANCE_POWER, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t referance_power_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_SET_REFERANCE_POWER); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_SET_REFERANCE_POWER]); +} +static CLASS_ATTR_RW(referance_power); + +static ssize_t nvt_referance_current_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_REFERANCE_CURRENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_REFERANCE_CURRENT]); +} +static CLASS_ATTR_RO(nvt_referance_current); + +static ssize_t nvt_referance_power_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_GET_REFERANCE_POWER); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_GET_REFERANCE_POWER]); +} +static CLASS_ATTR_RO(nvt_referance_power); + +static ssize_t fg1_cell1_vol_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_CELL1_VOL); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FG1_CELL1_VOL]); +} +static CLASS_ATTR_RO(fg1_cell1_vol); + +static ssize_t fg1_cell2_vol_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_CELL2_VOL); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FG1_CELL2_VOL]); +} +static CLASS_ATTR_RO(fg1_cell2_vol); + +static ssize_t fg_temp_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_TEMP_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_TEMP_MAX]); +} +static CLASS_ATTR_RO(fg_temp_max); + +static ssize_t fg_time_ot_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_TIME_OT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_TIME_OT]); +} +static CLASS_ATTR_RO(fg_time_ot); + +#if defined (CONFIG_DUAL_FUEL_GAUGE) +static ssize_t slave_chip_ok_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SLAVE_CHIP_OK); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SLAVE_CHIP_OK]); +} +static CLASS_ATTR_RO(slave_chip_ok); + +static ssize_t slave_authentic_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + bool val; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + bcdev->slave_battery_auth = val; + pr_err("slave_authentic_store: %d\n", val); + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SLAVE_AUTHENTIC, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t slave_authentic_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_SLAVE_AUTHENTIC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SLAVE_AUTHENTIC]); +} +static CLASS_ATTR_RW(slave_authentic); + +static ssize_t fg1_vol_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_VOL); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FG1_VOL]); +} +static CLASS_ATTR_RO(fg1_vol); + +static ssize_t fg1_soc_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_SOC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FG1_SOC]); +} +static CLASS_ATTR_RO(fg1_soc); + +static ssize_t fg1_temp_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_TEMP); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_TEMP]); +} +static CLASS_ATTR_RO(fg1_temp); + +static ssize_t fg1_ibatt_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_IBATT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_IBATT]); +} +static CLASS_ATTR_RO(fg1_ibatt); + +static ssize_t fg1_ChargingStatus_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_ChargingStatus); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%x\n", pst->prop[XM_PROP_FG1_ChargingStatus]); +} + +static CLASS_ATTR_RO(fg1_ChargingStatus); + +static ssize_t fg1_GaugingStatus_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_GaugingStatus); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%x\n", pst->prop[XM_PROP_FG1_GaugingStatus]); +} + +static CLASS_ATTR_RO(fg1_GaugingStatus); + +static ssize_t fg1_FullChargeFlag_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_FullChargeFlag); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_FullChargeFlag]); +} + +static CLASS_ATTR_RO(fg1_FullChargeFlag); + +static ssize_t fg2_vol_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_VOL); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FG2_VOL]); +} +static CLASS_ATTR_RO(fg2_vol); + +static ssize_t fg2_soc_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_SOC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FG2_SOC]); +} +static CLASS_ATTR_RO(fg2_soc); + +static ssize_t fg2_temp_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_TEMP); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_TEMP]); +} +static CLASS_ATTR_RO(fg2_temp); + +static ssize_t fg2_ibatt_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_IBATT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_IBATT]); +} +static CLASS_ATTR_RO(fg2_ibatt); + +static ssize_t fg2_qmax_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_QMAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_QMAX]); +} +static CLASS_ATTR_RO(fg2_qmax); + +static ssize_t fg2_rm_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_RM); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_RM]); +} +static CLASS_ATTR_RO(fg2_rm); + +static ssize_t fg2_fcc_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_FCC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_FCC]); +} +static CLASS_ATTR_RO(fg2_fcc); + +static ssize_t fg2_soh_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_SOH); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_SOH]); +} +static CLASS_ATTR_RO(fg2_soh); + +static ssize_t fg2_fcc_soh_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_FCC_SOH); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_FCC_SOH]); +} +static CLASS_ATTR_RO(fg2_fcc_soh); + +static ssize_t fg2_cycle_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_CYCLE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_CYCLE]); +} +static CLASS_ATTR_RO(fg2_cycle); + +static ssize_t fg2_fastcharge_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_FAST_CHARGE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_FAST_CHARGE]); +} +static CLASS_ATTR_RO(fg2_fastcharge); + +static ssize_t fg2_current_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_CURRENT_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_CURRENT_MAX]); +} +static CLASS_ATTR_RO(fg2_current_max); + +static ssize_t fg2_vol_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_VOL_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_VOL_MAX]); +} +static CLASS_ATTR_RO(fg2_vol_max); + +static ssize_t fg2_tsim_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_TSIM); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_TSIM]); +} +static CLASS_ATTR_RO(fg2_tsim); + +static ssize_t fg2_tambient_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_TAMBIENT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_TAMBIENT]); +} +static CLASS_ATTR_RO(fg2_tambient); + +static ssize_t fg2_tremq_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_TREMQ); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_TREMQ]); +} +static CLASS_ATTR_RO(fg2_tremq); + +static ssize_t fg2_tfullq_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_TFULLQ); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_TFULLQ]); +} +static CLASS_ATTR_RO(fg2_tfullq); + +static ssize_t fg2_ChargingStatus_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_ChargingStatus); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%x\n", pst->prop[XM_PROP_FG2_ChargingStatus]); +} + +static CLASS_ATTR_RO(fg2_ChargingStatus); + +static ssize_t fg2_GaugingStatus_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_GaugingStatus); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%x\n", pst->prop[XM_PROP_FG2_GaugingStatus]); +} + +static CLASS_ATTR_RO(fg2_GaugingStatus); + +static ssize_t fg2_FullChargeFlag_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_FullChargeFlag); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_FullChargeFlag]); +} + +static CLASS_ATTR_RO(fg2_FullChargeFlag); + +static ssize_t fg2_rsoc_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_RSOC); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_RSOC]); +} +static CLASS_ATTR_RO(fg2_rsoc); + +static ssize_t fg_voltage_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_VOLTAGE_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_VOLTAGE_MAX]); +} +static CLASS_ATTR_RO(fg_voltage_max); + +static ssize_t fg_charge_current_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_Charge_Current_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_Charge_Current_MAX]); +} + +static CLASS_ATTR_RO(fg_charge_current_max); + +static ssize_t fg_discharge_current_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_Discharge_Current_MAX); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_Discharge_Current_MAX]); +} + +static CLASS_ATTR_RO(fg_discharge_current_max); + +static ssize_t fg_temp_min_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_TEMP_MIN); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_TEMP_MIN]); +} +static CLASS_ATTR_RO(fg_temp_min); + +static ssize_t fg_time_ht_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_TIME_HT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_TIME_HT]); +} +static CLASS_ATTR_RO(fg_time_ht); + +static ssize_t fg_time_ut_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_TIME_UT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_TIME_UT]); +} +static CLASS_ATTR_RO(fg_time_ut); + +static ssize_t fg_time_lt_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_TIME_LT); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG_TIME_LT]); +} +static CLASS_ATTR_RO(fg_time_lt); + +static ssize_t fg_seal_set_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + + if (kstrtoint(buf, 0, &val)) + return -EINVAL; + + pr_err("seal set %d\n", val); + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_FG_SEAL_SET, val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t fg_seal_set_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG_SEAL_SET); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_FG_SEAL_SET]); +} +static CLASS_ATTR_RW(fg_seal_set); + +static ssize_t fg1_seal_state_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_SEAL_STATE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_SEAL_STATE]); +} +static CLASS_ATTR_RO(fg1_seal_state); + +static ssize_t fg2_seal_state_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_SEAL_STATE); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_SEAL_STATE]); +} +static CLASS_ATTR_RO(fg2_seal_state); + +static ssize_t fg1_df_check_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG1_DF_CHECK); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG1_DF_CHECK]); +} +static CLASS_ATTR_RO(fg1_df_check); + + +static ssize_t fg2_df_check_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + + rc = read_property_id(bcdev, pst, XM_PROP_FG2_DF_CHECK); + if (rc < 0) + return rc; + + return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[XM_PROP_FG2_DF_CHECK]); +} +static CLASS_ATTR_RO(fg2_df_check); + +#endif + +static ssize_t power_max_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *xm_pst = &bcdev->psy_list[PSY_TYPE_XM]; + union power_supply_propval val = {0, }; + struct power_supply *usb_psy = NULL; + int rc, usb_present = 0; + usb_psy = bcdev->psy_list[PSY_TYPE_USB].psy; + + if (usb_psy != NULL) { + rc = usb_psy_get_prop(usb_psy, POWER_SUPPLY_PROP_ONLINE, &val); + if (!rc) + usb_present = val.intval; + else + usb_present = 0; + pr_err("usb_present: %d\n", usb_present); + } + + if (usb_present) { + rc = read_property_id(bcdev, xm_pst, XM_PROP_APDO_MAX); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%u", xm_pst->prop[XM_PROP_APDO_MAX]); + } + + pr_err("tx_adapter:%d\n", xm_pst->prop[XM_PROP_TX_ADAPTER]); +#if defined(CONFIG_MI_WIRELESS) + switch(xm_pst->prop[XM_PROP_TX_ADAPTER]) + { + case ADAPTER_XIAOMI_PD_50W: + case ADAPTER_XIAOMI_PD_60W: + case ADAPTER_XIAOMI_PD_100W: + return scnprintf(buf, PAGE_SIZE, "%u", 50); + case ADAPTER_XIAOMI_PD_30W: + case ADAPTER_VOICE_BOX_30W: + return scnprintf(buf, PAGE_SIZE, "%u", 30); + case ADAPTER_XIAOMI_QC3_20W: + case ADAPTER_XIAOMI_PD_20W: + case ADAPTER_XIAOMI_CAR_20W: + return scnprintf(buf, PAGE_SIZE, "%u", 20); + default: + return scnprintf(buf, PAGE_SIZE, "%u", 0); + } +#endif + return scnprintf(buf, PAGE_SIZE, "%u", 0); +} +static CLASS_ATTR_RO(power_max); + +static ssize_t shipmode_count_reset_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SHIPMODE_COUNT_RESET, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t shipmode_count_reset_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_SHIPMODE_COUNT_RESET); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SHIPMODE_COUNT_RESET]); +} +static CLASS_ATTR_RW(shipmode_count_reset); + +static ssize_t sport_mode_store(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + int rc; + int val; + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SPORT_MODE, val); + if (rc < 0) + return rc; + return count; +} +static ssize_t sport_mode_show(struct class *c, + struct class_attribute *attr, char *buf) +{ + struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, + battery_class); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + int rc; + rc = read_property_id(bcdev, pst, XM_PROP_SPORT_MODE); + if (rc < 0) + return rc; + return scnprintf(buf, PAGE_SIZE, "%u\n", pst->prop[XM_PROP_SPORT_MODE]); +} +static CLASS_ATTR_RW(sport_mode); + +static struct attribute *xiaomi_battery_class_attrs[] = { + &class_attr_real_type.attr, + &class_attr_resistance_id.attr, + &class_attr_verify_digest.attr, + &class_attr_connector_temp.attr, + &class_attr_authentic.attr, + &class_attr_chip_ok.attr, + &class_attr_vbus_disable.attr, + &class_attr_verify_process.attr, + &class_attr_request_vdm_cmd.attr, + &class_attr_current_state.attr, + &class_attr_adapter_id.attr, + &class_attr_adapter_svid.attr, + &class_attr_pd_verifed.attr, + &class_attr_pdo2.attr, + &class_attr_bq2597x_chip_ok.attr, + &class_attr_bq2597x_slave_chip_ok.attr, + &class_attr_bq2597x_bus_current.attr, + &class_attr_bq2597x_slave_bus_current.attr, + &class_attr_bq2597x_bus_delta.attr, + &class_attr_bq2597x_bus_voltage.attr, + &class_attr_bq2597x_battery_present.attr, + &class_attr_bq2597x_slave_battery_present.attr, + &class_attr_bq2597x_battery_voltage.attr, + &class_attr_master_smb1396_online.attr, + &class_attr_master_smb1396_iin.attr, + &class_attr_slave_smb1396_online.attr, + &class_attr_slave_smb1396_iin.attr, + &class_attr_smb_iin_diff.attr, + &class_attr_cc_orientation.attr, + &class_attr_input_suspend.attr, + &class_attr_fastchg_mode.attr, + &class_attr_night_charging.attr, + &class_attr_shutdown_delay.attr, + &class_attr_soc_decimal.attr, + &class_attr_soc_decimal_rate.attr, + &class_attr_quick_charge_type.attr, + &class_attr_fake_cycle.attr, + &class_attr_fake_soh.attr, + &class_attr_fake_temp.attr, + &class_attr_thermal_remove.attr, + &class_attr_typec_mode.attr, + &class_attr_mtbf_current.attr, + &class_attr_smart_batt.attr, + &class_attr_shipmode_count_reset.attr, + &class_attr_sport_mode.attr, + &class_attr_apdo_max.attr, + &class_attr_verify_slave_flag.attr, + &class_attr_die_temperature.attr, + &class_attr_slave_die_temperature.attr, + &class_attr_battcont_online.attr, + &class_attr_battmoni_isc.attr, + &class_attr_battmoni_soa.attr, + &class_attr_over_peak_flag.attr, + &class_attr_current_deviation.attr, + &class_attr_power_deviation.attr, + &class_attr_average_current.attr, + &class_attr_average_temp.attr, + &class_attr_start_learn.attr, + &class_attr_stop_learn.attr, + &class_attr_set_learn_power.attr, + &class_attr_get_learn_power.attr, + &class_attr_get_learn_power_dev.attr, + &class_attr_get_learn_time_dev.attr, + &class_attr_constant_power.attr, + &class_attr_remaining_time.attr, + &class_attr_referance_power.attr, + &class_attr_nvt_referance_current.attr, + &class_attr_nvt_referance_power.attr, + &class_attr_start_learn_b.attr, + &class_attr_stop_learn_b.attr, + &class_attr_set_learn_power_b.attr, + &class_attr_get_learn_power_b.attr, + &class_attr_get_learn_power_dev_b.attr, + /* wireless charge attrs */ +#if defined(CONFIG_MI_WIRELESS) + &class_attr_tx_mac.attr, + &class_attr_rx_cr.attr, + &class_attr_rx_cep.attr, + &class_attr_bt_state.attr, + &class_attr_reverse_chg_mode.attr, + &class_attr_reverse_chg_state.attr, + &class_attr_wireless_chip_fw.attr, + &class_attr_wls_bin.attr, + &class_attr_rx_vout.attr, + &class_attr_rx_vrect.attr, + &class_attr_rx_iout.attr, + &class_attr_tx_adapter.attr, + &class_attr_op_mode.attr, + &class_attr_wls_die_temp.attr, + &class_attr_wlscharge_control_limit.attr, + &class_attr_wls_thermal_remove.attr, + &class_attr_wls_debug.attr, + &class_attr_wls_fw_state.attr, + &class_attr_wls_car_adapter.attr, + &class_attr_wls_tx_speed.attr, + &class_attr_wls_fc_flag.attr, +#endif + /*****************************/ + /*fuelgauge test node*/ + &class_attr_fg1_qmax.attr, + &class_attr_fg1_rm.attr, + &class_attr_fg1_fcc.attr, + &class_attr_fg1_soh.attr, + &class_attr_fg1_fcc_soh.attr, + &class_attr_fg1_cycle.attr, + &class_attr_fg1_fastcharge.attr, + &class_attr_fg1_current_max.attr, + &class_attr_fg1_vol_max.attr, + &class_attr_fg1_tsim.attr, + &class_attr_fg1_tambient.attr, + &class_attr_fg1_tremq.attr, + &class_attr_fg1_tfullq.attr, + &class_attr_fg1_rsoc.attr, + &class_attr_fg1_ai.attr, + &class_attr_fg1_cell1_vol.attr, + &class_attr_fg1_cell2_vol.attr, + &class_attr_power_max.attr, + &class_attr_fg_vendor.attr, + &class_attr_fg_temp_max.attr, + &class_attr_fg_time_ot.attr, + /* dual fuelgauge test node only for L18*/ +#if defined (CONFIG_DUAL_FUEL_GAUGE) + &class_attr_slave_chip_ok.attr, + &class_attr_slave_authentic.attr, + &class_attr_fg1_vol.attr, + &class_attr_fg1_soc.attr, + &class_attr_fg1_temp.attr, + &class_attr_fg1_ibatt.attr, + &class_attr_fg1_ChargingStatus.attr, + &class_attr_fg1_GaugingStatus.attr, + &class_attr_fg1_FullChargeFlag.attr, + &class_attr_fg2_vol.attr, + &class_attr_fg2_soc.attr, + &class_attr_fg2_temp.attr, + &class_attr_fg2_ibatt.attr, + &class_attr_fg2_qmax.attr, + &class_attr_fg2_rm.attr, + &class_attr_fg2_fcc.attr, + &class_attr_fg2_soh.attr, + &class_attr_fg2_fcc_soh.attr, + &class_attr_fg2_cycle.attr, + &class_attr_fg2_fastcharge.attr, + &class_attr_fg2_current_max.attr, + &class_attr_fg2_vol_max.attr, + &class_attr_fg2_tsim.attr, + &class_attr_fg2_tambient.attr, + &class_attr_fg2_tremq.attr, + &class_attr_fg2_tfullq.attr, + &class_attr_fg2_ChargingStatus.attr, + &class_attr_fg2_GaugingStatus.attr, + &class_attr_fg2_FullChargeFlag.attr, + &class_attr_fg2_rsoc.attr, + &class_attr_fg_voltage_max.attr, + &class_attr_fg_charge_current_max.attr, + &class_attr_fg_discharge_current_max.attr, + &class_attr_fg_temp_min.attr, + &class_attr_fg_time_ht.attr, + &class_attr_fg_time_ut.attr, + &class_attr_fg_time_lt.attr, + &class_attr_fg_seal_set.attr, + &class_attr_fg1_seal_state.attr, + &class_attr_fg1_df_check.attr, + &class_attr_fg2_seal_state.attr, + &class_attr_fg2_df_check.attr, +#endif +#if defined(CONFIG_BQ_CLOUD_AUTHENTICATION) + &class_attr_server_sn.attr, + &class_attr_server_result.attr, + &class_attr_adsp_result.attr, +#endif + NULL, +}; + +const struct attribute_group xiaomi_battery_class_group = { + .attrs = xiaomi_battery_class_attrs, +}; + +void generate_xm_charge_uvent(struct work_struct *work) +{ + struct battery_chg_dev *bcdev = container_of(work, struct battery_chg_dev, xm_prop_change_work.work); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_WLS]; + int prop_id, rc; + + dev_err(bcdev->dev,"%s+++", __func__); + + kobject_uevent_env(&bcdev->dev->kobj, KOBJ_CHANGE, NULL); + + prop_id = get_property_id(pst, POWER_SUPPLY_PROP_PRESENT); + if (prop_id < 0) + return; + rc = read_property_id(bcdev, pst, prop_id); + if (rc < 0) + return; + bcdev->boost_mode = pst->prop[WLS_BOOST_EN]; + + return; +} + +#define CHARGING_PERIOD_S 30 +void xm_charger_debug_info_print_work(struct work_struct *work) +{ + struct battery_chg_dev *bcdev = container_of(work, struct battery_chg_dev, charger_debug_info_print_work.work); + struct power_supply *usb_psy = NULL; + struct power_supply *wls_psy = NULL; + int rc, usb_present = 0, wls_present = 0; + int vbus_vol_uv = 0, ibus_ua = 0; + int interval = CHARGING_PERIOD_S; + union power_supply_propval val = {0, }; + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_XM]; + + usb_psy = bcdev->psy_list[PSY_TYPE_USB].psy; + if (usb_psy != NULL) { + rc = usb_psy_get_prop(usb_psy, POWER_SUPPLY_PROP_ONLINE, &val); + if (!rc) + usb_present = val.intval; + else + usb_present = 0; + pr_err("usb_present: %d\n", usb_present); + } else { + return; + } + +#if defined(CONFIG_MI_WIRELESS) + wls_psy = bcdev->psy_list[PSY_TYPE_WLS].psy; + if (wls_psy != NULL) { + rc = wls_psy_get_prop(wls_psy, POWER_SUPPLY_PROP_ONLINE, &val); + if (!rc) + wls_present = val.intval; + else + wls_present = 0; + pr_err("wls_present: %d\n", wls_present); + } else { + wls_present = 0; + } +#endif + + if ((usb_present == 1) || (wls_present == 1)) { + + rc = read_property_id(bcdev, pst, XM_PROP_FG_VENDOR_ID); + + if (usb_present == 1) { + rc = usb_psy_get_prop(usb_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); + if (!rc) + vbus_vol_uv = val.intval; + else + vbus_vol_uv = 0; + + rc = usb_psy_get_prop(usb_psy, POWER_SUPPLY_PROP_CURRENT_NOW, &val); + if (!rc) + ibus_ua = val.intval; + else + ibus_ua = 0; + + pr_err("chg_type= %s tl:= %d ffc:= %d, pd_verifed:= %d, FG_VENDOR_ID:= %d\n",get_usb_type_name(pst->prop[XM_PROP_REAL_TYPE]), + bcdev->curr_thermal_level, pst->prop[XM_PROP_FASTCHGMODE], pst->prop[XM_PROP_PD_VERIFED], pst->prop[XM_PROP_FG_VENDOR_ID]); + } else if(wls_present == 1) { + rc = wls_psy_get_prop(wls_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); + if (!rc) + vbus_vol_uv = val.intval; + else + vbus_vol_uv = 0; + + rc = wls_psy_get_prop(wls_psy, POWER_SUPPLY_PROP_CURRENT_NOW, &val); + if (!rc) + ibus_ua = val.intval; + else + ibus_ua = 0; + + rc = read_property_id(bcdev, pst, XM_PROP_RX_VOUT); + rc = read_property_id(bcdev, pst, XM_PROP_RX_IOUT); + rc = read_property_id(bcdev, pst, XM_PROP_WLS_FC_FLAG); + pr_err("tx_adapter=%d fc_flag=%d rxvout=%d rxiout=%d wlsthermal=%d ffc=%d, FG_VENDOR_ID=%d\n", + pst->prop[XM_PROP_TX_ADAPTER],pst->prop[XM_PROP_WLS_FC_FLAG],pst->prop[XM_PROP_RX_VOUT],pst->prop[XM_PROP_RX_IOUT], bcdev->curr_wlsthermal_level, pst->prop[XM_PROP_FASTCHGMODE], pst->prop[XM_PROP_FG_VENDOR_ID]); + } + + rc = read_property_id(bcdev, pst, XM_PROP_MTBF_CURRENT); + if (!rc && pst->prop[XM_PROP_MTBF_CURRENT] != bcdev->mtbf_current) { + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_MTBF_CURRENT, bcdev->mtbf_current); + pr_info("XM_PROP_MTBF_CURRENT = %d bcdev->mtbf_current = %d, re-set\n", pst->prop[XM_PROP_MTBF_CURRENT], bcdev->mtbf_current); + } + + rc = read_property_id(bcdev, pst, XM_PROP_AUTHENTIC); + if (!rc && !pst->prop[XM_PROP_AUTHENTIC] && bcdev->battery_auth) { + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_AUTHENTIC, bcdev->battery_auth); + pr_info("XM_PROP_AUTHENTIC = %d bcdev->battery_auth = %d, re-set battery auth\n", pst->prop[XM_PROP_AUTHENTIC], bcdev->battery_auth); + } + + rc = read_property_id(bcdev, pst, XM_PROP_SLAVE_AUTHENTIC); + if (!rc && !pst->prop[XM_PROP_SLAVE_AUTHENTIC] && bcdev->slave_battery_auth) { + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_SLAVE_AUTHENTIC, bcdev->slave_battery_auth); + pr_info("XM_PROP_SLAVE_AUTHENTIC = %d bcdev->slave_battery_auth = %d, re-set battery auth\n", pst->prop[XM_PROP_SLAVE_AUTHENTIC], bcdev->slave_battery_auth); + } + + pr_err("vbus_vol_uv: %d, ibus_ua: %d\n", vbus_vol_uv, ibus_ua); + interval = CHARGING_PERIOD_S; + schedule_delayed_work(&bcdev->charger_debug_info_print_work, interval * HZ); + bcdev->debug_work_en = 1; + } else { + bcdev->debug_work_en = 0; + } + +} + +#define MAX_UEVENT_LENGTH 50 +static int add_xiaomi_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct platform_device *pdev = container_of(dev, struct platform_device, dev); + struct battery_chg_dev *bcdev = platform_get_drvdata(pdev); + + char *prop_buf = NULL; + char uevent_string[MAX_UEVENT_LENGTH+1]; + u32 i = 0; + + prop_buf = (char *)get_zeroed_page(GFP_KERNEL); + if (!prop_buf) + return 0; + + /*add our prop start*/ +#if defined(CONFIG_MI_WIRELESS) + reverse_chg_state_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_REVERSE_CHG_STATE=%s", prop_buf); + add_uevent_var(env, uevent_string); + + + reverse_chg_mode_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_REVERSE_CHG_MODE=%s", prop_buf); + add_uevent_var(env, uevent_string); + + tx_mac_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_TX_MAC=%s", prop_buf); + add_uevent_var(env, uevent_string); + + rx_cep_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_RX_CEP=%s", prop_buf); + add_uevent_var(env, uevent_string); + + rx_cr_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_RX_CR=%s", prop_buf); + add_uevent_var(env, uevent_string); + + wls_fw_state_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_WLS_FW_STATE=%s", prop_buf); + add_uevent_var(env, uevent_string); + + wls_car_adapter_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_WLS_CAR_ADAPTER=%s", prop_buf); + add_uevent_var(env, uevent_string); + + tx_adapter_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_TX_ADAPTER=%s", prop_buf); + add_uevent_var(env, uevent_string); +#endif + + soc_decimal_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_SOC_DECIMAL=%s", prop_buf); + add_uevent_var(env, uevent_string); + + soc_decimal_rate_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_SOC_DECIMAL_RATE=%s", prop_buf); + add_uevent_var(env, uevent_string); + + shutdown_delay_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_SHUTDOWN_DELAY=%s", prop_buf); + add_uevent_var(env, uevent_string); + + quick_charge_type_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_QUICK_CHARGE_TYPE=%s", prop_buf); + add_uevent_var(env, uevent_string); + + connector_temp_show( &(bcdev->battery_class), NULL, prop_buf); + snprintf(uevent_string, MAX_UEVENT_LENGTH, "POWER_SUPPLY_CONNECTOR_TEMP=%s", prop_buf); + add_uevent_var(env, uevent_string); + + /*add our prop end*/ + + dev_err(bcdev->dev,"currnet uevent info :"); + for(i = 0; i < env->envp_idx; ++i){ + dev_err(bcdev->dev," %s ", env->envp[i]); + } + + free_page((unsigned long)prop_buf); + return 0; +} + +struct device_type dev_type_xiaomi_uevent = { + .name = "dev_type_xiaomi_uevent", + .uevent = add_xiaomi_uevent, +};