From 654b1238efbf670034721649b9fd5ad5b4f0fad6 Mon Sep 17 00:00:00 2001 From: Nicholas Troast Date: Tue, 20 Sep 2016 13:25:59 -0700 Subject: [PATCH 1/2] qpnp-smb2: support batteryless platforms Currently a device without a battery will shutdown soon after boot since the SOC will be 0. Add a DT property called "qcom,batteryless-platform" which indicates that the device does not have a battery. If this property is set then charging will be disabled, and all of the necessary battery parameters will be faked to ensure normal operation. Change-Id: I6943b7f5565ad95eddb9e3d30de5efbc47106e3d Signed-off-by: Nicholas Troast --- .../bindings/power/qcom-charger/qpnp-smb2.txt | 8 +++++--- arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi | 2 +- drivers/power/qcom-charger/qpnp-smb2.c | 18 +++++++++++------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt index 510a824fda79..1c5dd91891dc 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt @@ -21,11 +21,13 @@ Charger specific properties: Value type: Definition: "qcom,qpnp-smb2". -- qcom,suspend-input +- qcom,batteryless-platform Usage: optional Value type: - Definition: Boolean flag which indicates that the charger should not draw - current from any of its input sources (USB, DC). + Definition: Boolean flag which indicates that the platform does not have a + battery, and therefore charging should be disabled. In + addition battery properties will be faked such that the device + assumes normal operation. - qcom,fcc-max-ua Usage: optional diff --git a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi index d44002efea11..8c3e6c0ae667 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi @@ -418,7 +418,7 @@ }; &pmicobalt_charger { - qcom,suspend-input; + qcom,batteryless-platform; }; &pmicobalt_haptics { diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 7caa9548308a..32b374cbb67f 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -197,7 +197,7 @@ static struct smb_params v1_params = { #define STEP_CHARGING_MAX_STEPS 5 struct smb_dt_props { - bool suspend_input; + bool no_battery; int fcc_ua; int usb_icl_ua; int dc_icl_ua; @@ -256,8 +256,8 @@ static int smb2_parse_dt(struct smb2 *chip) if (rc < 0) chg->step_chg_enabled = false; - chip->dt.suspend_input = of_property_read_bool(node, - "qcom,suspend-input"); + chip->dt.no_battery = of_property_read_bool(node, + "qcom,batteryless-platform"); rc = of_property_read_u32(node, "qcom,fcc-max-ua", &chip->dt.fcc_ua); @@ -602,8 +602,9 @@ static int smb2_batt_get_prop(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { - int rc; - struct smb_charger *chg = power_supply_get_drvdata(psy); + struct smb2 *chip = power_supply_get_drvdata(psy); + struct smb_charger *chg = &chip->chg; + int rc = 0; switch (psp) { case POWER_SUPPLY_PROP_STATUS: @@ -929,6 +930,9 @@ static int smb2_init_hw(struct smb2 *chip) struct smb_charger *chg = &chip->chg; int rc; + if (chip->dt.no_battery) + chg->fake_capacity = 50; + if (chip->dt.fcc_ua < 0) smblib_get_charge_param(chg, &chg->param.fcc, &chip->dt.fcc_ua); @@ -949,9 +953,9 @@ static int smb2_init_hw(struct smb2 *chip) vote(chg->pl_disable_votable, CHG_STATE_VOTER, true, 0); vote(chg->usb_suspend_votable, - DEFAULT_VOTER, chip->dt.suspend_input, 0); + DEFAULT_VOTER, chip->dt.no_battery, 0); vote(chg->dc_suspend_votable, - DEFAULT_VOTER, chip->dt.suspend_input, 0); + DEFAULT_VOTER, chip->dt.no_battery, 0); vote(chg->fcc_max_votable, DEFAULT_VOTER, true, chip->dt.fcc_ua); vote(chg->fv_votable, From 9d4164b5e808c3d45a19ef803d5eaf0df0a4faf3 Mon Sep 17 00:00:00 2001 From: Nicholas Troast Date: Thu, 25 Aug 2016 10:59:21 -0700 Subject: [PATCH 2/2] 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 --- drivers/power/qcom-charger/fg-core.h | 1 + drivers/power/qcom-charger/fg-util.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index 08ec7334737e..a609d8fcd400 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -252,4 +252,5 @@ extern int fg_ima_init(struct fg_chip *chip); 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 5f133d6f39c1..0d52fb5ba9b8 100644 --- a/drivers/power/qcom-charger/fg-util.c +++ b/drivers/power/qcom-charger/fg-util.c @@ -29,6 +29,26 @@ static struct fg_dbgfs dbgfs_data = { }, }; +#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;