google_battery: add debug sysfs to fake cell fault detection status
-- add a debug sysfs to fake single battery disconnect
- /d/bpst/bpst_sbd_status
-- TODO: to finish the implementation when the detection
algorithm in b/203019566 lockdown
Bug: 203019566
Signed-off-by: Jack Wu <[email protected]>
Change-Id: I137b279ac5d73588b71f3772828df3498e3f60eb
diff --git a/google_battery.c b/google_battery.c
index 44557f2..9665985 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -208,6 +208,14 @@
int res_temp_high;
};
+/* battery pack status */
+struct batt_bpst {
+ struct mutex lock;
+ bool bpst_enable;
+ /* single battery disconnect status */
+ int bpst_sbd_status;
+};
+
enum batt_paired_state {
BATT_PAIRING_WRITE_ERROR = -4,
BATT_PAIRING_READ_ERROR = -3,
@@ -440,6 +448,9 @@
/* battery power metrics */
struct power_metrics power_metrics;
+
+ /* battery pack status */
+ struct batt_bpst bpst_state;
};
static int gbatt_get_temp(const struct batt_drv *batt_drv, int *temp);
@@ -3451,6 +3462,35 @@
}
}
+/* cell fault: disconnect of one of the battery cells */
+static bool batt_cell_fault_detect(struct batt_bpst *bpst_state)
+{
+ int bpst_sbd_status;
+
+ /*
+ * fake bpst_sbd_status by "echo 1 > /d/bpst/bpst_sbd_status"
+ * TODO: will implement the code from the algo in b/203019566
+ */
+ bpst_sbd_status = bpst_state->bpst_sbd_status;
+
+ /* report detection result*/
+ bpst_state->bpst_sbd_status = 0;
+
+ return !!bpst_sbd_status;
+}
+
+static int batt_init_bpst_profile(struct batt_drv *batt_drv)
+{
+ struct batt_bpst *bpst_state = &batt_drv->bpst_state;
+ struct device_node *node = batt_drv->device->of_node;
+
+ bpst_state->bpst_enable = of_property_read_bool(node, "google,bpst-enable");
+ if (!bpst_state->bpst_enable)
+ return -EINVAL;
+
+ return 0;
+}
+
/* called holding chg_lock */
static int batt_chg_logic(struct batt_drv *batt_drv)
{
@@ -3476,6 +3516,16 @@
if (chg_state_is_disconnected(chg_state)) {
const qnum_t ssoc_delta = ssoc_get_delta(batt_drv);
+ /* update bpst */
+ mutex_lock(&batt_drv->bpst_state.lock);
+ if (batt_drv->bpst_state.bpst_enable) {
+ bool cell_fault_detect = batt_cell_fault_detect(&batt_drv->bpst_state);
+
+ if (cell_fault_detect)
+ pr_info("MSC_BPST: cell_fault_detect in disconnected\n");
+ }
+ mutex_unlock(&batt_drv->bpst_state.lock);
+
if (batt_drv->ssoc_state.buck_enabled == 0)
goto msc_logic_exit;
@@ -4303,6 +4353,32 @@
}
BATTERY_DEBUG_ATTRIBUTE(debug_power_metrics_fops, debug_get_power_metrics, NULL);
+
+static int debug_bpst_sbd_status_read(void *data, u64 *val)
+{
+ struct batt_drv *batt_drv = (struct batt_drv *)data;
+
+ *val = batt_drv->bpst_state.bpst_sbd_status;
+ return 0;
+}
+
+static int debug_bpst_sbd_status_write(void *data, u64 val)
+{
+ struct batt_drv *batt_drv = (struct batt_drv *)data;
+
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+ mutex_lock(&batt_drv->bpst_state.lock);
+ batt_drv->bpst_state.bpst_sbd_status = val;
+ mutex_unlock(&batt_drv->bpst_state.lock);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_bpst_sbd_status_fops,
+ debug_bpst_sbd_status_read,
+ debug_bpst_sbd_status_write, "%llu\n");
#endif
/* ------------------------------------------------------------------------- */
@@ -5926,6 +6002,22 @@
return 0;
}
+/* bpst detection */
+static int batt_bpst_init_fs(struct batt_drv *batt_drv)
+{
+ if (batt_drv->bpst_state.bpst_enable) {
+ struct dentry *de = NULL;
+
+ de = debugfs_create_dir("bpst", 0);
+ if (IS_ERR_OR_NULL(de))
+ return 0;
+
+ debugfs_create_file("bpst_sbd_status", 0600, de, batt_drv,
+ &debug_bpst_sbd_status_fops);
+ }
+ return 0;
+}
+
/* ------------------------------------------------------------------------- */
/* could also use battery temperature, age */
@@ -7115,6 +7207,7 @@
mutex_init(&batt_drv->batt_lock);
mutex_init(&batt_drv->stats_lock);
mutex_init(&batt_drv->cc_data.lock);
+ mutex_init(&batt_drv->bpst_state.lock);
if (!batt_drv->fg_psy) {
@@ -7188,6 +7281,11 @@
batt_drv->sd.is_enable = false;
}
+ /* init bpst setting */
+ ret = batt_init_bpst_profile(batt_drv);
+ if (ret < 0)
+ pr_err("bpst profile disabled, ret=%d\n", ret);
+
/* cycle count is cached: read here bc SSOC, chg_profile might use it */
batt_update_cycle_count(batt_drv);
@@ -7358,6 +7456,9 @@
/* debugfs */
(void)batt_init_fs(batt_drv);
+ /* bpst */
+ (void)batt_bpst_init_fs(batt_drv);
+
/* power metrics */
schedule_delayed_work(&batt_drv->power_metrics.work,
msecs_to_jiffies(batt_drv->power_metrics.polling_rate * 1000));