power: qpnp-qg: Add CYCLE_COUNT property

Currently, CYCLE_COUNTS property shows the bucket cycle
counters as a string. Add CYCLE_COUNT property in QG that can
provide an average of all the bucket counters.

Move the helper functions that gets the cycle_counts and
cycle_count property to fg-alg.c so that it can re-used.

CRs-Fixed: 2238261
Change-Id: I18c32590c4c30e6d347284b43ac0a408614c0ffa
Signed-off-by: Vamshi Krishna B V <vbv@codeaurora.org>
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
index f1ce5b3..9b9a880 100644
--- a/drivers/power/supply/qcom/fg-alg.c
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -164,13 +164,13 @@
 }
 
 /**
- * get_cycle_count -
+ * get_bucket_cycle_count -
  * @counter: Cycle counter object
  *
  * Returns the cycle counter for a SOC bucket.
  *
  */
-int get_cycle_count(struct cycle_counter *counter)
+static int get_bucket_cycle_count(struct cycle_counter *counter)
 {
 	int count;
 
@@ -187,6 +187,68 @@
 }
 
 /**
+ * get_cycle_counts -
+ * @counter: Cycle counter object
+ * @buf: Bucket cycle counts formatted in a string returned to the caller
+ *
+ * Get cycle count for all buckets in a string format
+ */
+int get_cycle_counts(struct cycle_counter *counter, const char **buf)
+{
+	int i, rc, len = 0;
+
+	for (i = 1; i <= BUCKET_COUNT; i++) {
+		counter->id = i;
+		rc = get_bucket_cycle_count(counter);
+		if (rc < 0) {
+			pr_err("Couldn't get cycle count rc=%d\n", rc);
+			return rc;
+		}
+
+		if (sizeof(counter->str_buf) - len < 8) {
+			pr_err("Invalid length %d\n", len);
+			return -EINVAL;
+		}
+
+		len += snprintf(counter->str_buf+len, 8, "%d ", rc);
+	}
+
+	counter->str_buf[len] = '\0';
+	*buf = counter->str_buf;
+	return 0;
+}
+
+/**
+ * get_cycle_count -
+ * @counter: Cycle counter object
+ * @count: Average cycle count returned to the caller
+ *
+ * Get average cycle count for all buckets
+ */
+int get_cycle_count(struct cycle_counter *counter, int *count)
+{
+	int i, rc, temp = 0;
+
+	for (i = 1; i <= BUCKET_COUNT; i++) {
+		counter->id = i;
+		rc = get_bucket_cycle_count(counter);
+		if (rc < 0) {
+			pr_err("Couldn't get cycle count rc=%d\n", rc);
+			return rc;
+		}
+
+		temp += rc;
+	}
+
+	/*
+	 * Normalize the counter across each bucket so that we can get
+	 * the overall charge cycle count.
+	 */
+	*count = temp / BUCKET_COUNT;
+	return 0;
+}
+
+/**
  * cycle_count_init -
  * @counter: Cycle counter object
  *
diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h
index 0853ad9..7c25007 100644
--- a/drivers/power/supply/qcom/fg-alg.h
+++ b/drivers/power/supply/qcom/fg-alg.h
@@ -21,6 +21,7 @@
 	bool		started[BUCKET_COUNT];
 	u16		count[BUCKET_COUNT];
 	u8		last_soc[BUCKET_COUNT];
+	char		str_buf[BUCKET_COUNT * 8];
 	int		id;
 	int		last_bucket;
 	struct mutex	lock;
@@ -61,7 +62,8 @@
 void clear_cycle_count(struct cycle_counter *counter);
 void cycle_count_update(struct cycle_counter *counter, int batt_soc,
 		int charge_status, bool charge_done, bool input_present);
-int get_cycle_count(struct cycle_counter *counter);
+int get_cycle_count(struct cycle_counter *counter, int *count);
+int get_cycle_counts(struct cycle_counter *counter, const char **buf);
 int cycle_count_init(struct cycle_counter *counter);
 void cap_learning_abort(struct cap_learning *cl);
 void cap_learning_update(struct cap_learning *cl, int batt_temp,
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index 05ca452..a1aeac2 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -126,7 +126,6 @@
 	struct cap_learning	*cl;
 	/* charge counter */
 	struct cycle_counter	*counter;
-	char			counter_buf[BUCKET_COUNT * 8];
 };
 
 enum ocv_type {
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index 09705ad..14b9205 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -1171,32 +1171,6 @@
 	return 0;
 }
 
-static const char *qg_get_cycle_counts(struct qpnp_qg *chip)
-{
-	int i, rc, len = 0;
-	char *buf;
-
-	buf = chip->counter_buf;
-	for (i = 1; i <= BUCKET_COUNT; i++) {
-		chip->counter->id = i;
-		rc = get_cycle_count(chip->counter);
-		if (rc < 0) {
-			pr_err("Couldn't get cycle count rc=%d\n", rc);
-			return NULL;
-		}
-
-		if (sizeof(chip->counter_buf) - len < 8) {
-			pr_err("Invalid length %d\n", len);
-			return NULL;
-		}
-
-		len += snprintf(buf+len, 8, "%d ", rc);
-	}
-
-	buf[len] = '\0';
-	return buf;
-}
-
 static int qg_psy_set_property(struct power_supply *psy,
 			       enum power_supply_property psp,
 			       const union power_supply_propval *pval)
@@ -1302,7 +1276,12 @@
 			pval->intval = (int)temp;
 		break;
 	case POWER_SUPPLY_PROP_CYCLE_COUNTS:
-		pval->strval = qg_get_cycle_counts(chip);
+		rc = get_cycle_counts(chip->counter, &pval->strval);
+		if (rc < 0)
+			pval->strval = NULL;
+		break;
+	case POWER_SUPPLY_PROP_CYCLE_COUNT:
+		rc = get_cycle_count(chip->counter, &pval->intval);
 		break;
 	default:
 		pr_debug("Unsupported property %d\n", psp);
@@ -1340,6 +1319,7 @@
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_BATT_FULL_CURRENT,
 	POWER_SUPPLY_PROP_BATT_PROFILE_VERSION,
+	POWER_SUPPLY_PROP_CYCLE_COUNT,
 	POWER_SUPPLY_PROP_CYCLE_COUNTS,
 	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,