qcom-charger: fg-util: add float decode function

Some SRAM registers are encoded using a floating point representation.
Add a function to decode these registers into signed micro-unit
integers.

The exponent and mantissa are signed integers represented by two's
complement, and the exponent value is offset by -9. This is a half
float representation stored as:

EEEEE MMMMMMMMMMM

Where E are the exponent bits, and M are the mantissa bits.

To decode this representation the following formula is applied:
2^(exponent - 9) * mantissa

Change-Id: Id9f28a0eeb2a904aca41eb46d0215d80287e0b88
Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h
index 08ec733..a609d8f 100644
--- a/drivers/power/qcom-charger/fg-core.h
+++ b/drivers/power/qcom-charger/fg-core.h
@@ -252,4 +252,5 @@
 extern int fg_sram_debugfs_create(struct fg_chip *chip);
 extern void fill_string(char *str, size_t str_len, u8 *buf, int buf_len);
 extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos);
+extern s64 fg_float_decode(u16 val);
 #endif
diff --git a/drivers/power/qcom-charger/fg-util.c b/drivers/power/qcom-charger/fg-util.c
index 609a3ff..b30b880 100644
--- a/drivers/power/qcom-charger/fg-util.c
+++ b/drivers/power/qcom-charger/fg-util.c
@@ -29,6 +29,26 @@
 	},
 };
 
+#define EXPONENT_SHIFT		11
+#define EXPONENT_OFFSET		-9
+#define MANTISSA_SIGN_BIT	10
+#define MICRO_UNIT		1000000
+s64 fg_float_decode(u16 val)
+{
+	s8 exponent;
+	s32 mantissa;
+
+	/* mantissa bits are shifted out during sign extension */
+	exponent = ((s16)val >> EXPONENT_SHIFT) + EXPONENT_OFFSET;
+	/* exponent bits are shifted out during sign extension */
+	mantissa = sign_extend32(val, MANTISSA_SIGN_BIT) * MICRO_UNIT;
+
+	if (exponent < 0)
+		return (s64)mantissa >> -exponent;
+
+	return (s64)mantissa << exponent;
+}
+
 void fill_string(char *str, size_t str_len, u8 *buf, int buf_len)
 {
 	int pos = 0;