From a2ac6b286dc36fb5104fc0d06ab0f023e9de8c15 Mon Sep 17 00:00:00 2001 From: Arian Date: Thu, 13 Oct 2022 19:56:07 +0200 Subject: [PATCH] power: supply: qti_battery_charger: Apply xiaomi changes From branch: zijin-s-oss Change-Id: Ieb19795ff69250b2c425392e6a1e9b6c4dd814e1 --- drivers/power/supply/Kconfig | 36 ++ drivers/power/supply/qti_battery_charger.c | 479 +++++++++++++++++++-- drivers/power/supply/qti_battery_charger.h | 195 +++++++++ 3 files changed, 686 insertions(+), 24 deletions(-) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 114cf8bdf27b..c8714ecb15b7 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -418,6 +418,42 @@ config QTI_BATTERY_CHARGER To compile the driver as a module, choose M here: the module will be called qti_battery_charger. +config BQ2597X + bool "BQ2597X charger" + depends on QTI_BATTERY_CHARGER + help + Say Y here to enable BQ2597X charger + +config BQ_FG_1S + bool "BQ 1S battery cell config" + depends on QTI_BATTERY_CHARGER + help + Say Y here to enable BQ 1S battery cell + +config BQ_FUEL_GAUGE + bool "BQ fuel gauge config" + depends on QTI_BATTERY_CHARGER + help + Say Y here to enable BQ fuel gauge + +config DUAL_FUEL_GAUGE + bool "Dual fuel gauge" + depends on QTI_BATTERY_CHARGER + help + Say Y here to enable dual fuel gauge + +config MI_WIRELESS + bool "mi wireless config" + depends on QTI_BATTERY_CHARGER + help + Say Y here to enable mi wireless + +config RENOIR_FOR_BUILD + bool "renoir build debug" + depends on QTI_BATTERY_CHARGER + help + Say Y here to enable renoir build debug + config CHARGER_88PM860X tristate "Marvell 88PM860x Charger driver" depends on MFD_88PM860X && BATTERY_88PM860X diff --git a/drivers/power/supply/qti_battery_charger.c b/drivers/power/supply/qti_battery_charger.c index e1d0bfeedb5c..cf049a07a789 100644 --- a/drivers/power/supply/qti_battery_charger.c +++ b/drivers/power/supply/qti_battery_charger.c @@ -5,6 +5,7 @@ #define pr_fmt(fmt) "BATTERY_CHG: %s: " fmt, __func__ +#include #include #include #include @@ -21,6 +22,11 @@ #include #include +#if defined(CONFIG_BQ_FUEL_GAUGE) +#include +#include +#endif + #include "qti_battery_charger.h" #include "qti_typec_class.h" @@ -36,6 +42,7 @@ static const int battery_prop_map[BATT_PROP_MAX] = { [BATT_CURR_NOW] = POWER_SUPPLY_PROP_CURRENT_NOW, [BATT_CHG_CTRL_LIM] = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, [BATT_CHG_CTRL_LIM_MAX] = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, + [BATT_CONSTANT_CURRENT] = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, [BATT_TEMP] = POWER_SUPPLY_PROP_TEMP, [BATT_TECHNOLOGY] = POWER_SUPPLY_PROP_TECHNOLOGY, [BATT_CHG_COUNTER] = POWER_SUPPLY_PROP_CHARGE_COUNTER, @@ -67,6 +74,10 @@ static const int wls_prop_map[WLS_PROP_MAX] = { [WLS_VOLT_MAX] = POWER_SUPPLY_PROP_VOLTAGE_MAX, [WLS_CURR_NOW] = POWER_SUPPLY_PROP_CURRENT_NOW, [WLS_CURR_MAX] = POWER_SUPPLY_PROP_CURRENT_MAX, + [WLS_TX_ADAPTER] = POWER_SUPPLY_PROP_TX_ADAPTER, +}; + +static const int xm_prop_map[XM_PROP_MAX] = { }; static const unsigned int bcdev_usb_extcon_cable[] = { @@ -77,13 +88,14 @@ static const unsigned int bcdev_usb_extcon_cable[] = { /* Standard usb_type definitions similar to power_supply_sysfs.c */ static const char * const power_supply_usb_type_text[] = { - "Unknown", "SDP", "DCP", "CDP", "ACA", "C", - "PD", "PD_DRP", "PD_PPS", "BrickID" + "Unknown", "USB", "USB_DCP", "USB_CDP", "USB_ACA", "USB_C", + "USB_PD", "PD_DRP", "PD_PPS", "BrickID", "USB_HVDCP", + "USB_HVDCP3","USB_HVDCP3P5", "USB_FLOAT" }; /* Custom usb_type definitions */ static const char * const qc_power_supply_usb_type_text[] = { - "HVDCP", "HVDCP_3", "HVDCP_3P5" + "HVDCP", "HVDCP_3", "HVDCP_3P5","USB_FLOAT","HVDCP_3" }; static int battery_chg_fw_write(struct battery_chg_dev *bcdev, void *data, @@ -139,14 +151,13 @@ static int battery_chg_write(struct battery_chg_dev *bcdev, void *data, if (!rc) { pr_err("Error, timed out sending message\n"); mutex_unlock(&bcdev->rw_lock); - return -ETIMEDOUT; } rc = 0; } mutex_unlock(&bcdev->rw_lock); - return rc; + return 0; } static int write_property_id(struct battery_chg_dev *bcdev, @@ -281,6 +292,13 @@ EXPORT_SYMBOL(qti_battery_charger_get_prop); static bool validate_message(struct battery_charger_resp_msg *resp_msg, size_t len) { + struct xm_verify_digest_resp_msg *verify_digest_resp_msg = (struct xm_verify_digest_resp_msg *)resp_msg; + struct xm_ss_auth_resp_msg *ss_auth_resp_msg = (struct xm_ss_auth_resp_msg *)resp_msg; + + if (len == sizeof(*verify_digest_resp_msg) || len == sizeof(*ss_auth_resp_msg)) { + return true; + } + if (len != sizeof(*resp_msg)) { pr_err("Incorrect response length %zu for opcode %#x\n", len, resp_msg->hdr.opcode); @@ -297,12 +315,17 @@ static bool validate_message(struct battery_charger_resp_msg *resp_msg, return true; } +static struct power_supply_desc usb_psy_desc; + #define MODEL_DEBUG_BOARD "Debug_Board" static void handle_message(struct battery_chg_dev *bcdev, void *data, size_t len) { struct battery_charger_resp_msg *resp_msg = data; struct battery_model_resp_msg *model_resp_msg = data; + struct xm_verify_digest_resp_msg *verify_digest_resp_msg = data; + struct xm_ss_auth_resp_msg *ss_auth_resp_msg = data; + struct wls_fw_resp_msg *wls_fw_ver_resp_msg = data; struct wireless_fw_check_resp *fw_check_msg; struct wireless_fw_push_buf_resp *fw_resp_msg; struct wireless_fw_update_status *fw_update_msg; @@ -336,22 +359,70 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data, if (validate_message(resp_msg, len) && resp_msg->property_id < pst->prop_count) { pst->prop[resp_msg->property_id] = resp_msg->value; + if (resp_msg->property_id == USB_ADAP_TYPE) { + switch (resp_msg->value) { + case ADAP_TYPE_DCP: + usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP; + break; + case ADAP_TYPE_CDP: + usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_CDP; + break; + case ADAP_TYPE_PD: + usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD; + break; + case ADAP_TYPE_SDP: + usb_psy_desc.type = POWER_SUPPLY_TYPE_USB; + break; + default: + break; + } + } ack_set = true; } break; case BC_WLS_STATUS_GET: pst = &bcdev->psy_list[PSY_TYPE_WLS]; + + /* Handle model response uniquely as it's a string */ + if (pst->version && len == sizeof(*wls_fw_ver_resp_msg)) { + memcpy(pst->version, wls_fw_ver_resp_msg->version, MAX_STR_LEN); + ack_set = true; + break; + } + if (validate_message(resp_msg, len) && resp_msg->property_id < pst->prop_count) { pst->prop[resp_msg->property_id] = resp_msg->value; ack_set = true; } + break; + case BC_XM_STATUS_GET: + pst = &bcdev->psy_list[PSY_TYPE_XM]; + + /* Handle digest response uniquely as it's a string */ + if (bcdev->digest && len == sizeof(*verify_digest_resp_msg)) { + memcpy(bcdev->digest, verify_digest_resp_msg->digest, BATTERY_DIGEST_LEN); + ack_set = true; + break; + } + if (bcdev->ss_auth_data && len == sizeof(*ss_auth_resp_msg)) { + memcpy(bcdev->ss_auth_data, ss_auth_resp_msg->data, BATTERY_SS_AUTH_DATA_LEN*sizeof(u32)); + ack_set = true; + break; + } + if (validate_message(resp_msg, len) && + resp_msg->property_id < pst->prop_count) { + pst->prop[resp_msg->property_id] = resp_msg->value; + ack_set = true; + } + break; case BC_BATTERY_STATUS_SET: case BC_USB_STATUS_SET: case BC_WLS_STATUS_SET: + case BC_XM_STATUS_SET: if (validate_message(data, len)) ack_set = true; @@ -465,8 +536,6 @@ static void battery_chg_update_uusb_type(struct battery_chg_dev *bcdev, } } -static struct power_supply_desc usb_psy_desc; - static void battery_chg_update_usb_type_work(struct work_struct *work) { struct battery_chg_dev *bcdev = container_of(work, @@ -496,6 +565,7 @@ static void battery_chg_update_usb_type_work(struct work_struct *work) case QTI_POWER_SUPPLY_USB_TYPE_HVDCP: case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3: case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5: + case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3_CLASSB: usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP; break; case POWER_SUPPLY_USB_TYPE_CDP: @@ -513,13 +583,23 @@ static void battery_chg_update_usb_type_work(struct work_struct *work) usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD; break; default: - usb_psy_desc.type = POWER_SUPPLY_TYPE_USB; + usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN; break; } battery_chg_update_uusb_type(bcdev, pst->prop[USB_ADAP_TYPE]); } +static void battery_chg_fb_notifier_work(struct work_struct *work) +{ + struct battery_chg_dev *bcdev = container_of(work, + struct battery_chg_dev, fb_notifier_work); + int rc; + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_FB_BLANK_STATE, bcdev->blank_state); +} + static void handle_notification(struct battery_chg_dev *bcdev, void *data, size_t len) { @@ -545,6 +625,9 @@ static void handle_notification(struct battery_chg_dev *bcdev, void *data, case BC_WLS_STATUS_GET: pst = &bcdev->psy_list[PSY_TYPE_WLS]; break; + case BC_XM_STATUS_GET: + schedule_delayed_work(&bcdev->xm_prop_change_work, 0); + break; default: break; } @@ -559,7 +642,8 @@ static void handle_notification(struct battery_chg_dev *bcdev, void *data, * unplugged). */ power_supply_changed(pst->psy); - pm_wakeup_dev_event(bcdev->dev, 50, true); + if (!bcdev->reverse_chg_flag) + pm_wakeup_dev_event(bcdev->dev, 50, true); } } @@ -627,6 +711,9 @@ static enum power_supply_property wls_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_MAX, +#if defined(CONFIG_MI_WIRELESS) + POWER_SUPPLY_PROP_TX_ADAPTER, +#endif }; static const struct power_supply_desc wls_psy_desc = { @@ -644,7 +731,7 @@ static const char *get_usb_type_name(u32 usb_type) u32 i; if (usb_type >= QTI_POWER_SUPPLY_USB_TYPE_HVDCP && - usb_type <= QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5) { + usb_type <= QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3_CLASSB) { for (i = 0; i < ARRAY_SIZE(qc_power_supply_usb_type_text); i++) { if (i == (usb_type - QTI_POWER_SUPPLY_USB_TYPE_HVDCP)) @@ -700,6 +787,135 @@ static int usb_psy_set_icl(struct battery_chg_dev *bcdev, u32 prop_id, int val) return rc; } +typedef enum { + POWER_SUPPLY_USB_REAL_TYPE_HVDCP2=0x80, + POWER_SUPPLY_USB_REAL_TYPE_HVDCP3=0x81, + POWER_SUPPLY_USB_REAL_TYPE_HVDCP3P5=0x82, + POWER_SUPPLY_USB_REAL_TYPE_USB_FLOAT=0x83, + POWER_SUPPLY_USB_REAL_TYPE_HVDCP3_CLASSB=0x84, +} power_supply_usb_type; + +struct quick_charge { + int adap_type; + enum power_supply_quick_charge_type adap_cap; +}; + +struct quick_charge adapter_cap[11] = { + { POWER_SUPPLY_USB_TYPE_SDP, QUICK_CHARGE_NORMAL }, + { POWER_SUPPLY_USB_TYPE_DCP, QUICK_CHARGE_NORMAL }, + { POWER_SUPPLY_USB_TYPE_CDP, QUICK_CHARGE_NORMAL }, + { POWER_SUPPLY_USB_TYPE_ACA, QUICK_CHARGE_NORMAL }, + { POWER_SUPPLY_USB_REAL_TYPE_USB_FLOAT, QUICK_CHARGE_NORMAL }, + { POWER_SUPPLY_USB_TYPE_PD, QUICK_CHARGE_FAST }, + { POWER_SUPPLY_USB_REAL_TYPE_HVDCP2, QUICK_CHARGE_FAST }, + { POWER_SUPPLY_USB_REAL_TYPE_HVDCP3, QUICK_CHARGE_FAST }, + { POWER_SUPPLY_USB_REAL_TYPE_HVDCP3_CLASSB, QUICK_CHARGE_FLASH }, + { POWER_SUPPLY_USB_REAL_TYPE_HVDCP3P5, QUICK_CHARGE_FLASH }, + {0, 0}, +}; + +#define ADAPTER_NONE 0x0 +#define ADAPTER_XIAOMI_QC3_20W 0x9 +#define ADAPTER_XIAOMI_PD_20W 0xa +#define ADAPTER_XIAOMI_CAR_20W 0xb +#define ADAPTER_XIAOMI_PD_30W 0xc +#define ADAPTER_VOICE_BOX_30W 0xd +#define ADAPTER_XIAOMI_PD_50W 0xe +#define ADAPTER_XIAOMI_PD_60W 0xf +#define ADAPTER_XIAOMI_PD_100W 0x10 +static u8 get_quick_charge_type(struct battery_chg_dev *bcdev) +{ + int i = 0,verify_digiest = 0; + u8 rc; + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY]; + enum power_supply_usb_type real_charger_type = 0; + int batt_health; + u32 apdo_max; +#if defined(CONFIG_MI_WIRELESS) + u32 tx_adapter = 0; +#endif + rc = read_property_id(bcdev, pst, BATT_HEALTH); + if (rc < 0) + return rc; + batt_health = pst->prop[BATT_HEALTH]; + + pst = &bcdev->psy_list[PSY_TYPE_USB]; + rc = read_property_id(bcdev, pst, USB_REAL_TYPE); + if (rc < 0) + return rc; + real_charger_type = pst->prop[USB_REAL_TYPE]; + pst = &bcdev->psy_list[PSY_TYPE_XM]; + rc = read_property_id(bcdev, pst, XM_PROP_PD_VERIFED); + verify_digiest = pst->prop[XM_PROP_PD_VERIFED]; + + rc = read_property_id(bcdev, pst, XM_PROP_APDO_MAX); + apdo_max = pst->prop[XM_PROP_APDO_MAX]; + +#if defined(CONFIG_MI_WIRELESS) + rc = read_property_id(bcdev, pst, XM_PROP_TX_ADAPTER); + tx_adapter = pst->prop[XM_PROP_TX_ADAPTER]; +#endif + + if ((batt_health == POWER_SUPPLY_HEALTH_COLD) ||(batt_health == POWER_SUPPLY_HEALTH_WARM) + || (batt_health == POWER_SUPPLY_HEALTH_OVERHEAT) || (batt_health == POWER_SUPPLY_HEALTH_OVERVOLTAGE)) + return QUICK_CHARGE_NORMAL; + + if (real_charger_type == POWER_SUPPLY_USB_TYPE_PD_PPS && verify_digiest == 1) { + if (apdo_max >= 50) + return QUICK_CHARGE_SUPER; + else + return QUICK_CHARGE_TURBE; + } + else if(real_charger_type == POWER_SUPPLY_USB_TYPE_PD_PPS) + return QUICK_CHARGE_FAST; + +#if defined(CONFIG_MI_WIRELESS) + switch(tx_adapter) + { + case ADAPTER_NONE: + break; + case ADAPTER_XIAOMI_QC3_20W: + case ADAPTER_XIAOMI_PD_20W: + case ADAPTER_XIAOMI_CAR_20W: + case ADAPTER_XIAOMI_PD_30W: + case ADAPTER_VOICE_BOX_30W: + return QUICK_CHARGE_TURBE; + case ADAPTER_XIAOMI_PD_50W: + case ADAPTER_XIAOMI_PD_60W: + case ADAPTER_XIAOMI_PD_100W: + return QUICK_CHARGE_SUPER; + default: + return QUICK_CHARGE_NORMAL; + } +#endif + + while (adapter_cap[i].adap_type != 0) { + if (real_charger_type == adapter_cap[i].adap_type) { + return adapter_cap[i].adap_cap; + } + i++; + } + + return QUICK_CHARGE_NORMAL; +} + +static int battery_psy_set_fcc(struct battery_chg_dev *bcdev, u32 prop_id, int val) +{ + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY]; + u32 temp; + int rc; + + temp = val; + if (val < 0) + temp = UINT_MAX; + + rc = write_property_id(bcdev, pst, prop_id, temp); + if (!rc) + pr_debug("Set FCC to %u\n", temp); + + return rc; +} + static int usb_psy_get_prop(struct power_supply *psy, enum power_supply_property prop, union power_supply_propval *pval) @@ -709,6 +925,11 @@ static int usb_psy_get_prop(struct power_supply *psy, int prop_id, rc; pval->intval = -ENODATA; + if (prop == POWER_SUPPLY_PROP_QUICK_CHARGE_TYPE) + { + pval->intval = get_quick_charge_type(bcdev); + return 0; + } prop_id = get_property_id(pst, prop); if (prop_id < 0) @@ -770,6 +991,7 @@ static enum power_supply_property usb_props[] = { POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, POWER_SUPPLY_PROP_USB_TYPE, POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_QUICK_CHARGE_TYPE, POWER_SUPPLY_PROP_SCOPE, }; @@ -824,7 +1046,11 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev, int val) { int rc; - u32 fcc_ua, prev_fcc_ua; + //u32 fcc_ua, prev_fcc_ua; + + if(val == bcdev->curr_thermal_level) + return 0; + pr_err("set thermal-level: %d num_thermal_levels: %d \n", val, bcdev->num_thermal_levels); if (!bcdev->num_thermal_levels) return 0; @@ -834,9 +1060,17 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev, return -EINVAL; } - if (val < 0 || val > bcdev->num_thermal_levels) + if (val < 0 || val >= bcdev->num_thermal_levels) return -EINVAL; + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_BATTERY], + BATT_CHG_CTRL_LIM, val); + if (rc < 0) + pr_err("Failed to set ccl:%d, rc=%d\n", val, rc); + + bcdev->curr_thermal_level = val; + +#if 0 fcc_ua = bcdev->thermal_levels[val]; prev_fcc_ua = bcdev->thermal_fcc_ua; bcdev->thermal_fcc_ua = fcc_ua; @@ -846,6 +1080,7 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev, bcdev->curr_thermal_level = val; else bcdev->thermal_fcc_ua = prev_fcc_ua; +#endif return rc; } @@ -907,10 +1142,19 @@ static int battery_psy_set_prop(struct power_supply *psy, const union power_supply_propval *pval) { struct battery_chg_dev *bcdev = power_supply_get_drvdata(psy); + struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY]; + int prop_id, rc = 0; + + prop_id = get_property_id(pst, prop); + if (prop_id < 0) + return prop_id; switch (prop) { case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: return battery_psy_set_charge_current(bcdev, pval->intval); + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + rc = battery_psy_set_fcc(bcdev, prop_id, pval->intval); + break; default: return -EINVAL; } @@ -923,6 +1167,7 @@ static int battery_psy_prop_is_writeable(struct power_supply *psy, { switch (prop) { case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: return 1; default: break; @@ -943,6 +1188,7 @@ static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_CHARGE_COUNTER, @@ -959,6 +1205,9 @@ static enum power_supply_property battery_props[] = { static const struct power_supply_desc batt_psy_desc = { .name = "battery", +#if defined(CONFIG_BQ_FUEL_GAUGE) + .no_thermal = true, +#endif .type = POWER_SUPPLY_TYPE_BATTERY, .properties = battery_props, .num_properties = ARRAY_SIZE(battery_props), @@ -967,10 +1216,52 @@ static const struct power_supply_desc batt_psy_desc = { .property_is_writeable = battery_psy_prop_is_writeable, }; +#if defined(CONFIG_BQ_FUEL_GAUGE) +static int power_supply_read_temp(struct thermal_zone_device *tzd, + int *temp) +{ + struct power_supply *psy; + struct battery_chg_dev *bcdev = NULL; + struct psy_state *pst = NULL; + int rc = 0, batt_temp; + static int last_temp; + ktime_t time_now; + static ktime_t last_read_time; + s64 delta; + + WARN_ON(tzd == NULL); + psy = tzd->devdata; + bcdev = power_supply_get_drvdata(psy); + pst = &bcdev->psy_list[PSY_TYPE_XM]; + + time_now = ktime_get(); + delta = ktime_ms_delta(time_now, last_read_time); + if(delta < 5000){ + batt_temp = last_temp; + } else { + rc = read_property_id(bcdev, pst, XM_PROP_THERMAL_TEMP); + batt_temp = pst->prop[XM_PROP_THERMAL_TEMP]; + last_temp = batt_temp; + last_read_time = time_now; + } + + *temp = batt_temp * 1000; + pr_err("batt_thermal temp:%d ,delta:%ld blank_state=%d chg_type=%s tl:=%d ffc:=%d, pd_verifed:=%d\n", + batt_temp,delta, bcdev->blank_state, power_supply_usb_type_text[pst->prop[XM_PROP_REAL_TYPE]], + bcdev->curr_thermal_level, pst->prop[XM_PROP_FASTCHGMODE], pst->prop[XM_PROP_PD_VERIFED]); + return 0; +} + +static struct thermal_zone_device_ops psy_tzd_ops = { + .get_temp = power_supply_read_temp, +}; +#endif + static int battery_chg_init_psy(struct battery_chg_dev *bcdev) { struct power_supply_config psy_cfg = {}; int rc; + struct power_supply *psy; psy_cfg.drv_data = bcdev; psy_cfg.of_node = bcdev->dev->of_node; @@ -982,6 +1273,11 @@ static int battery_chg_init_psy(struct battery_chg_dev *bcdev) pr_err("Failed to register battery power supply, rc=%d\n", rc); return rc; } + psy = bcdev->psy_list[PSY_TYPE_BATTERY].psy; +#if defined(CONFIG_BQ_FUEL_GAUGE) + psy->tzd = thermal_zone_device_register(psy->desc->name, + 0, 0, psy, &psy_tzd_ops, NULL, 0, 0); +#endif bcdev->psy_list[PSY_TYPE_USB].psy = devm_power_supply_register(bcdev->dev, &usb_psy_desc, &psy_cfg); @@ -1534,10 +1830,20 @@ static ssize_t ship_mode_en_store(struct class *c, struct class_attribute *attr, { struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev, battery_class); + struct battery_charger_ship_mode_req_msg msg = { { 0 } }; + int rc =0; if (kstrtobool(buf, &bcdev->ship_mode_en)) return -EINVAL; + msg.hdr.owner = MSG_OWNER_BC; + msg.hdr.type = MSG_TYPE_REQ_RESP; + msg.hdr.opcode = BC_SHIP_MODE_REQ_SET; + msg.ship_mode_type = SHIP_MODE_PMIC; + rc = battery_chg_write(bcdev, &msg, sizeof(msg)); + if (rc < 0) + pr_err("Failed to write ship mode: %d\n", rc); + return count; } @@ -1607,8 +1913,8 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) { struct device_node *node = bcdev->dev->of_node; struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY]; - int i, rc, len; - u32 prev, val; + int rc, len; + //u32 prev,i, val; of_property_read_string(node, "qcom,wireless-fw-name", &bcdev->wls_fw_name); @@ -1620,6 +1926,7 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) len = rc; +#if 0 rc = read_property_id(bcdev, pst, BATT_CHG_CTRL_LIM_MAX); if (rc < 0) { pr_err("Failed to read prop BATT_CHG_CTRL_LIM_MAX, rc=%d\n", @@ -1643,6 +1950,7 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) prev = val; } +#endif bcdev->thermal_levels = devm_kcalloc(bcdev->dev, len + 1, sizeof(*bcdev->thermal_levels), @@ -1664,29 +1972,23 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev) return rc; } - bcdev->num_thermal_levels = len; + bcdev->num_thermal_levels = MAX_THERMAL_LEVEL; bcdev->thermal_fcc_ua = pst->prop[BATT_CHG_CTRL_LIM_MAX]; + bcdev->support_wireless_charge = of_property_read_bool(node, "mi,support-wireless"); + bcdev->support_2s_charging = of_property_read_bool(node, "mi,support-2s-charging"); + return 0; } static int battery_chg_ship_mode(struct notifier_block *nb, unsigned long code, void *unused) { - struct battery_charger_notify_msg msg_notify = { { 0 } }; struct battery_charger_ship_mode_req_msg msg = { { 0 } }; struct battery_chg_dev *bcdev = container_of(nb, struct battery_chg_dev, reboot_notifier); int rc; - msg_notify.hdr.owner = MSG_OWNER_BC; - msg_notify.hdr.type = MSG_TYPE_NOTIFY; - msg_notify.hdr.opcode = BC_SHUTDOWN_NOTIFY; - - rc = battery_chg_write(bcdev, &msg_notify, sizeof(msg_notify)); - if (rc < 0) - pr_err("Failed to send shutdown notification rc=%d\n", rc); - if (!bcdev->ship_mode_en) return NOTIFY_DONE; @@ -1704,6 +2006,61 @@ static int battery_chg_ship_mode(struct notifier_block *nb, unsigned long code, return NOTIFY_DONE; } +static int battery_chg_shutdown(struct notifier_block *nb, unsigned long code, + void *unused) +{ + struct battery_charger_shutdown_req_msg msg = { { 0 } }; + struct battery_chg_dev *bcdev = container_of(nb, struct battery_chg_dev, + shutdown_notifier); + int rc; + + msg.hdr.owner = MSG_OWNER_BC; + msg.hdr.type = MSG_TYPE_REQ_RESP; + msg.hdr.opcode = BC_SHUTDOWN_REQ_SET; + + if (code == SYS_POWER_OFF || code == SYS_RESTART) { + pr_err("start adsp shutdown\n"); + rc = battery_chg_write(bcdev, &msg, sizeof(msg)); + if (rc < 0) + pr_emerg("Failed to write ship mode: %d\n", rc); + } + + return NOTIFY_DONE; +} + +#define FB_BLANK 1 +#define FB_UNBLANK 0 +static int fb_notifier_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct battery_chg_dev *bcdev = container_of(nb, struct battery_chg_dev, + fb_notifier); + struct mi_disp_notifier *evdata = data; + unsigned int blank; + int rc; + + if(val != MI_DISP_DPMS_EVENT) + return NOTIFY_OK; + + if (evdata && evdata->data && bcdev) { + blank = *(int *)(evdata->data); + pr_debug("val:%lu,blank:%u\n", val, blank); + + if ((blank == MI_DISP_DPMS_POWERDOWN || + blank == MI_DISP_DPMS_LP1 || blank == MI_DISP_DPMS_LP2)) { + bcdev->blank_state = FB_BLANK; + } else if (blank == MI_DISP_DPMS_ON) { + bcdev->blank_state = FB_UNBLANK; + } + + rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_XM], + XM_PROP_FB_BLANK_STATE, bcdev->blank_state); + if (rc < 0) + return rc; + } + return NOTIFY_OK; +} + static int register_extcon_conn_type(struct battery_chg_dev *bcdev) { struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB]; @@ -1752,6 +2109,9 @@ static int battery_chg_probe(struct platform_device *pdev) struct pmic_glink_client_data client_data = { }; int rc, i; + dev_err(dev, "battery_chg_probe start\n"); + msleep(50); + bcdev = devm_kzalloc(&pdev->dev, sizeof(*bcdev), GFP_KERNEL); if (!bcdev) return -ENOMEM; @@ -1768,6 +2128,10 @@ static int battery_chg_probe(struct platform_device *pdev) bcdev->psy_list[PSY_TYPE_WLS].prop_count = WLS_PROP_MAX; bcdev->psy_list[PSY_TYPE_WLS].opcode_get = BC_WLS_STATUS_GET; bcdev->psy_list[PSY_TYPE_WLS].opcode_set = BC_WLS_STATUS_SET; + bcdev->psy_list[PSY_TYPE_XM].map = xm_prop_map; + bcdev->psy_list[PSY_TYPE_XM].prop_count = XM_PROP_MAX; + bcdev->psy_list[PSY_TYPE_XM].opcode_get = BC_XM_STATUS_GET; + bcdev->psy_list[PSY_TYPE_XM].opcode_set = BC_XM_STATUS_SET; for (i = 0; i < PSY_TYPE_MAX; i++) { bcdev->psy_list[i].prop = @@ -1781,6 +2145,17 @@ static int battery_chg_probe(struct platform_device *pdev) devm_kzalloc(&pdev->dev, MAX_STR_LEN, GFP_KERNEL); if (!bcdev->psy_list[PSY_TYPE_BATTERY].model) return -ENOMEM; + bcdev->digest= + devm_kzalloc(&pdev->dev, BATTERY_DIGEST_LEN, GFP_KERNEL); + if (!bcdev->digest) + return -ENOMEM; + bcdev->ss_auth_data= + devm_kzalloc(&pdev->dev, BATTERY_SS_AUTH_DATA_LEN * sizeof(u32), GFP_KERNEL); + if (!bcdev->ss_auth_data) + return -ENOMEM; + + bcdev->psy_list[PSY_TYPE_WLS].version = + devm_kzalloc(&pdev->dev, MAX_STR_LEN, GFP_KERNEL); mutex_init(&bcdev->rw_lock); init_completion(&bcdev->ack); @@ -1788,6 +2163,8 @@ static int battery_chg_probe(struct platform_device *pdev) init_completion(&bcdev->fw_update_ack); INIT_WORK(&bcdev->subsys_up_work, battery_chg_subsys_up_work); INIT_WORK(&bcdev->usb_type_work, battery_chg_update_usb_type_work); + INIT_WORK(&bcdev->fb_notifier_work, battery_chg_fb_notifier_work); + atomic_set(&bcdev->state, PMIC_GLINK_STATE_UP); bcdev->dev = dev; @@ -1811,6 +2188,22 @@ static int battery_chg_probe(struct platform_device *pdev) bcdev->reboot_notifier.priority = 255; register_reboot_notifier(&bcdev->reboot_notifier); + /* register shutdown notifier to do something before shutdown */ + bcdev->shutdown_notifier.notifier_call = battery_chg_shutdown; + bcdev->shutdown_notifier.priority = 255; + register_reboot_notifier(&bcdev->shutdown_notifier); + + bcdev->fb_notifier.notifier_call = fb_notifier_callback; +#if !defined(CONFIG_RENOIR_FOR_BUILD) + rc = mi_disp_register_client(&bcdev->fb_notifier); +#else + rc = 0; +#endif + if (rc < 0) { + dev_err(dev, "Failed to register disp notifier rc=%d\n", rc); + goto error; + } + rc = battery_chg_parse_dt(bcdev); if (rc < 0) { dev_err(dev, "Failed to parse dt rc=%d\n", rc); @@ -1850,11 +2243,26 @@ static int battery_chg_probe(struct platform_device *pdev) schedule_work(&bcdev->usb_type_work); + schedule_delayed_work(&bcdev->charger_debug_info_print_work, 5 * HZ); + + bcdev->slave_fg_verify_flag = false; + bcdev->shutdown_delay_en = true; + bcdev->reverse_chg_flag = 0; + bcdev->hw_version_build = 0; + +#if defined(CONFIG_BQ_FUEL_GAUGE) + bcdev->hw_version_build = get_hw_id_value(); +#endif + + dev_err(dev, "battery_chg_probe done\n"); return 0; error: bcdev->initialized = false; complete(&bcdev->ack); pmic_glink_unregister_client(bcdev->client); +#if !defined(CONFIG_RENOIR_FOR_BUILD) + mi_disp_unregister_client(&bcdev->fb_notifier); +#endif unregister_reboot_notifier(&bcdev->reboot_notifier); return rc; } @@ -1867,6 +2275,9 @@ static int battery_chg_remove(struct platform_device *pdev) device_init_wakeup(bcdev->dev, false); debugfs_remove_recursive(bcdev->debugfs_dir); class_unregister(&bcdev->battery_class); +#if !defined(CONFIG_RENOIR_FOR_BUILD) + mi_disp_unregister_client(&bcdev->fb_notifier); +#endif unregister_reboot_notifier(&bcdev->reboot_notifier); qti_typec_class_deinit(bcdev->typec_class); rc = pmic_glink_unregister_client(bcdev->client); @@ -1877,16 +2288,36 @@ static int battery_chg_remove(struct platform_device *pdev) return 0; } +static int chg_suspend(struct device *dev) +{ + //struct battery_chg_dev *bcdev = dev_get_drvdata(dev); + pr_err("chg suspend\n"); + return 0; +} + +static int chg_resume(struct device *dev) +{ + //struct battery_chg_dev *bcdev = dev_get_drvdata(dev); + + pr_err("chg resume\n"); + return 0; +} static const struct of_device_id battery_chg_match_table[] = { { .compatible = "qcom,battery-charger" }, {}, }; +static const struct dev_pm_ops chg_pm_ops = { + .resume = chg_resume, + .suspend = chg_suspend, +}; + static struct platform_driver battery_chg_driver = { .driver = { .name = "qti_battery_charger", .of_match_table = battery_chg_match_table, + .pm = &chg_pm_ops, }, .probe = battery_chg_probe, .remove = battery_chg_remove, diff --git a/drivers/power/supply/qti_battery_charger.h b/drivers/power/supply/qti_battery_charger.h index 432050e7b913..2f8f27aae360 100644 --- a/drivers/power/supply/qti_battery_charger.h +++ b/drivers/power/supply/qti_battery_charger.h @@ -9,6 +9,8 @@ #define MSG_TYPE_NOTIFY 2 /* opcode for battery charger */ +#define BC_XM_STATUS_GET 0x50 +#define BC_XM_STATUS_SET 0x51 #define BC_SET_NOTIFY_REQ 0x04 #define BC_NOTIFY_IND 0x07 #define BC_BATTERY_STATUS_GET 0x30 @@ -18,6 +20,7 @@ #define BC_WLS_STATUS_GET 0x34 #define BC_WLS_STATUS_SET 0x35 #define BC_SHIP_MODE_REQ_SET 0x36 +#define BC_SHUTDOWN_REQ_SET 0x37 #define BC_WLS_FW_CHECK_UPDATE 0x40 #define BC_WLS_FW_PUSH_BUF_REQ 0x41 #define BC_WLS_FW_UPDATE_STATUS_RESP 0x42 @@ -35,6 +38,20 @@ #define WLS_FW_BUF_SIZE 128 #define DEFAULT_RESTRICT_FCC_UA 1000000 +#if defined(CONFIG_BQ_FG_1S) +#define BATTERY_DIGEST_LEN 32 +#else +#define BATTERY_DIGEST_LEN 20 +#endif +#define BATTERY_SS_AUTH_DATA_LEN 4 + +#define ADAP_TYPE_SDP 1 +#define ADAP_TYPE_CDP 3 +#define ADAP_TYPE_DCP 2 +#define ADAP_TYPE_PD 6 + +#define MAX_THERMAL_LEVEL 16 + enum usb_connector_type { USB_CONNECTOR_TYPE_TYPEC, USB_CONNECTOR_TYPE_MICRO_USB, @@ -44,6 +61,7 @@ enum psy_type { PSY_TYPE_BATTERY, PSY_TYPE_USB, PSY_TYPE_WLS, + PSY_TYPE_XM, PSY_TYPE_MAX, }; @@ -66,6 +84,7 @@ enum battery_property_id { BATT_CURR_NOW, BATT_CHG_CTRL_LIM, BATT_CHG_CTRL_LIM_MAX, + BATT_CONSTANT_CURRENT, BATT_TEMP, BATT_TECHNOLOGY, BATT_CHG_COUNTER, @@ -108,13 +127,148 @@ enum wireless_property_id { WLS_CURR_MAX, WLS_TYPE, WLS_BOOST_EN, + WLS_FW_VER, + WLS_TX_ADAPTER, + WLS_REGISTER, + WLS_INPUT_CURR, WLS_PROP_MAX, }; +enum xm_property_id { + XM_PROP_RESISTANCE_ID, + XM_PROP_VERIFY_DIGEST, + XM_PROP_CONNECTOR_TEMP, + XM_PROP_AUTHENTIC, + XM_PROP_CHIP_OK, +#if defined(CONFIG_DUAL_FUEL_GAUGE) + XM_PROP_SLAVE_CHIP_OK, + XM_PROP_SLAVE_AUTHENTIC, + XM_PROP_FG1_VOL, + XM_PROP_FG1_SOC, + XM_PROP_FG1_TEMP, + XM_PROP_FG1_IBATT, + XM_PROP_FG2_VOL, + XM_PROP_FG2_SOC, + XM_PROP_FG2_TEMP, + XM_PROP_FG2_IBATT, + XM_PROP_FG2_QMAX, + XM_PROP_FG2_RM, + XM_PROP_FG2_FCC, + XM_PROP_FG2_SOH, + XM_PROP_FG2_FCC_SOH, + XM_PROP_FG2_CYCLE, + XM_PROP_FG2_FAST_CHARGE, + XM_PROP_FG2_CURRENT_MAX, + XM_PROP_FG2_VOL_MAX, + XM_PROP_FG2_TSIM, + XM_PROP_FG2_TAMBIENT, + XM_PROP_FG2_TREMQ, + XM_PROP_FG2_TFULLQ, + XM_PROP_IS_OLD_HW, +#endif + XM_PROP_SOC_DECIMAL, + XM_PROP_SOC_DECIMAL_RATE, + XM_PROP_SHUTDOWN_DELAY, + XM_PROP_VBUS_DISABLE, + XM_PROP_CC_ORIENTATION, + XM_PROP_SLAVE_BATT_PRESENT, +#if defined(CONFIG_BQ2597X) + XM_PROP_BQ2597X_CHIP_OK, + XM_PROP_BQ2597X_SLAVE_CHIP_OK, + XM_PROP_BQ2597X_BUS_CURRENT, + XM_PROP_BQ2597X_SLAVE_BUS_CURRENT, + XM_PROP_BQ2597X_BUS_DELTA, + XM_PROP_BQ2597X_BUS_VOLTAGE, + XM_PROP_BQ2597X_BATTERY_PRESENT, + XM_PROP_BQ2597X_SLAVE_BATTERY_PRESENT, + XM_PROP_BQ2597X_BATTERY_VOLTAGE, + XM_PROP_COOL_MODE, +#endif + XM_PROP_BT_TRANSFER_START, + XM_PROP_MASTER_SMB1396_ONLINE, + XM_PROP_MASTER_SMB1396_IIN, + XM_PROP_SLAVE_SMB1396_ONLINE, + XM_PROP_SLAVE_SMB1396_IIN, + XM_PROP_SMB_IIN_DIFF, + /* wireless charge infor */ + XM_PROP_TX_MACL, + XM_PROP_TX_MACH, + XM_PROP_RX_CRL, + XM_PROP_RX_CRH, + XM_PROP_RX_CEP, + XM_PROP_BT_STATE, + XM_PROP_REVERSE_CHG_MODE, + XM_PROP_REVERSE_CHG_STATE, + XM_PROP_WLS_FW_STATE, + XM_PROP_RX_VOUT, + XM_PROP_RX_VRECT, + XM_PROP_RX_IOUT, + XM_PROP_TX_ADAPTER, + XM_PROP_OP_MODE, + XM_PROP_WLS_DIE_TEMP, + XM_PROP_WLS_CAR_ADAPTER, + XM_PROP_WLS_TX_SPEED, + /**********************/ + XM_PROP_INPUT_SUSPEND, + XM_PROP_REAL_TYPE, + /*used for pd authentic*/ + XM_PROP_VERIFY_PROCESS, + XM_PROP_VDM_CMD_CHARGER_VERSION, + XM_PROP_VDM_CMD_CHARGER_VOLTAGE, + XM_PROP_VDM_CMD_CHARGER_TEMP, + XM_PROP_VDM_CMD_SESSION_SEED, + XM_PROP_VDM_CMD_AUTHENTICATION, + XM_PROP_VDM_CMD_VERIFIED, + XM_PROP_VDM_CMD_REMOVE_COMPENSATION, + XM_PROP_VDM_CMD_REVERSE_AUTHEN, + XM_PROP_CURRENT_STATE, + XM_PROP_ADAPTER_ID, + XM_PROP_ADAPTER_SVID, + XM_PROP_PD_VERIFED, + XM_PROP_PDO2, + XM_PROP_UVDM_STATE, + /* use for MI SMART INTERCHG */ + XM_PROP_VDM_CMD_SINK_SOC, + /*****************/ + XM_PROP_WLS_BIN, + XM_PROP_FASTCHGMODE, + XM_PROP_APDO_MAX, + XM_PROP_THERMAL_REMOVE, + XM_PROP_VOTER_DEBUG, + XM_PROP_FG_RM, + XM_PROP_WLSCHARGE_CONTROL_LIMIT, + XM_PROP_MTBF_CURRENT, + XM_PROP_FAKE_TEMP, + XM_PROP_QBG_VBAT, + XM_PROP_QBG_VPH_PWR, + XM_PROP_QBG_TEMP, + XM_PROP_FB_BLANK_STATE, + XM_PROP_THERMAL_TEMP, + XM_PROP_TYPEC_MODE, + XM_PROP_NIGHT_CHARGING, + XM_PROP_SMART_BATT, + XM_PROP_FG1_QMAX, + XM_PROP_FG1_RM, + XM_PROP_FG1_FCC, + XM_PROP_FG1_SOH, + XM_PROP_FG1_FCC_SOH, + XM_PROP_FG1_CYCLE, + XM_PROP_FG1_FAST_CHARGE, + XM_PROP_FG1_CURRENT_MAX, + XM_PROP_FG1_VOL_MAX, + XM_PROP_FG1_TSIM, + XM_PROP_FG1_TAMBIENT, + XM_PROP_FG1_TREMQ, + XM_PROP_FG1_TFULLQ, + XM_PROP_FG_UPDATE_TIME, + XM_PROP_MAX, +}; enum { QTI_POWER_SUPPLY_USB_TYPE_HVDCP = 0x80, QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3, QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5, + QTI_POWER_SUPPLY_USB_TYPE_USB_FLOAT, + QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3_CLASSB, }; struct battery_charger_set_notify_msg { @@ -144,12 +298,27 @@ struct battery_charger_resp_msg { u32 ret_code; }; +struct wls_fw_resp_msg { + struct pmic_glink_hdr hdr; + u32 property_id; + u32 value; + char version[MAX_STR_LEN]; +}; + struct battery_model_resp_msg { struct pmic_glink_hdr hdr; u32 property_id; char model[MAX_STR_LEN]; }; + +struct xm_verify_digest_resp_msg { + struct pmic_glink_hdr hdr; + u32 property_id; + u8 digest[BATTERY_DIGEST_LEN]; + bool slave_fg; +}; + struct wireless_fw_check_req { struct pmic_glink_hdr hdr; u32 fw_version; @@ -192,9 +361,20 @@ struct battery_charger_ship_mode_req_msg { u32 ship_mode_type; }; +struct battery_charger_shutdown_req_msg { + struct pmic_glink_hdr hdr; +}; + +struct xm_ss_auth_resp_msg { + struct pmic_glink_hdr hdr; + u32 property_id; + u32 data[BATTERY_SS_AUTH_DATA_LEN]; +}; + struct psy_state { struct power_supply *psy; char *model; + char *version; const int *map; u32 *prop; u32 prop_count; @@ -213,15 +393,20 @@ struct battery_chg_dev { struct completion fw_update_ack; struct psy_state psy_list[PSY_TYPE_MAX]; struct dentry *debugfs_dir; + u8 *digest; + bool slave_fg_verify_flag; + u32 *ss_auth_data; /* extcon for VBUS/ID notification for USB for micro USB */ struct extcon_dev *extcon; u32 *thermal_levels; const char *wls_fw_name; int curr_thermal_level; + int curr_wlsthermal_level; int num_thermal_levels; atomic_t state; struct work_struct subsys_up_work; struct work_struct usb_type_work; + struct work_struct fb_notifier_work; int fake_soc; bool block_tx; bool ship_mode_en; @@ -230,13 +415,23 @@ struct battery_chg_dev { u32 wls_fw_version; u16 wls_fw_crc; struct notifier_block reboot_notifier; + struct notifier_block fb_notifier; + struct notifier_block shutdown_notifier; + int blank_state; u32 thermal_fcc_ua; u32 restrict_fcc_ua; u32 last_fcc_ua; u32 usb_icl_ua; + u32 reverse_chg_flag; + u32 hw_version_build; u32 connector_type; u32 usb_prev_mode; bool restrict_chg_en; + bool shutdown_delay_en; + bool support_wireless_charge; + bool support_2s_charging; + struct delayed_work xm_prop_change_work; + struct delayed_work charger_debug_info_print_work; /* To track the driver initialization status */ bool initialized; };