Loading Documentation/devicetree/bindings/power/smb1360-charger-fg.txt +15 −1 Original line number Diff line number Diff line Loading @@ -79,6 +79,16 @@ Optional Properties: is specified. This value is calculated from the batt-capacity and then encoded as floating number. cc_soc_coeff = HALF_ENCODING(8192 / batt-capacity) - qcom,fg-cutoff-voltage-mv This is the minimum allowed system voltage. The FG will report SOC = 0 at this volatge. This value is in mv. - qcom,fg-iterm-ma This is termination current at which the Monotonic SOC reports 100. The value passed here is negated in the driver (assuming that the iterm is always -ve). This value is in mA. - qcom,fg-ibatt-standby-ma This is the minimum current value for the SOC to be above 0% at the cutoff voltage. This value is in mA. Example: i2c@f9967000 { Loading @@ -100,7 +110,11 @@ Example: /* battery capacity */ qcom,fg-batt-capacity-mah = <4000>; qcom,fg-cc-soc-coeff = <0x8009> qcom,fg-cc-soc-coeff = <0x8009>; qcom,fg-cutoff-voltage-mv = <3300>; qcom,fg-iterm-ma = <100>; qcom,fg-ibatt-standby-ma = <200>; qcom,float-voltage-mv = <4200>; qcom,iterm-ma = <100>; Loading drivers/power/smb1360-charger-fg.c +105 −27 Original line number Diff line number Diff line Loading @@ -199,6 +199,9 @@ #define CC_TO_SOC_COEFF 0xBA #define ACTUAL_CAPACITY_REG 0xBE #define FG_SYS_CUTOFF_V_REG 0xD3 #define FG_ITERM_REG 0xD9 #define FG_IBATT_STANDBY_REG 0xCF #define FG_I2C_CFG_MASK SMB1360_MASK(2, 1) #define FG_CFG_I2C_ADDR 0x2 Loading Loading @@ -272,6 +275,9 @@ struct smb1360_chip { int voltage_empty_mv; int batt_capacity_mah; int cc_soc_coeff; int v_cutoff_mv; int fg_iterm_ma; int fg_ibatt_standby_ma; /* status tracking */ bool usb_present; Loading Loading @@ -2512,29 +2518,36 @@ static int smb1360_fg_config(struct smb1360_chip *chip) } /* scratch-pad register config */ if (chip->batt_capacity_mah != -EINVAL) { if (chip->batt_capacity_mah != -EINVAL || chip->v_cutoff_mv != -EINVAL || chip->fg_iterm_ma != -EINVAL || chip->fg_ibatt_standby_ma != -EINVAL) { rc = smb1360_enable_fg_access(chip); if (rc) { pr_err("Couldn't enable FG access rc=%d\n", rc); return rc; } /* Update battery capacity */ if (chip->batt_capacity_mah != -EINVAL) { rc = smb1360_read_bytes(chip, ACTUAL_CAPACITY_REG, reg2, 2); if (rc) { pr_err("Failed to read NOM CAPACITY rc=%d\n", pr_err("Failed to read ACTUAL CAPACITY rc=%d\n", rc); goto disable_fg; } fcc_mah = (reg2[1] << 8) | reg2[0]; if (fcc_mah == chip->batt_capacity_mah) { pr_debug("battery capacity correct\n"); goto disable_fg; } } else { /* Update the battery capacity */ reg2[1] = (chip->batt_capacity_mah & 0xFF00) >> 8; reg2[1] = (chip->batt_capacity_mah & 0xFF00) >> 8; reg2[0] = (chip->batt_capacity_mah & 0xFF); rc = smb1360_write_bytes(chip, ACTUAL_CAPACITY_REG, reg2, 2); rc = smb1360_write_bytes(chip, ACTUAL_CAPACITY_REG, reg2, 2); if (rc) { pr_err("Couldn't write batt-capacity rc=%d\n", rc); Loading @@ -2542,16 +2555,66 @@ static int smb1360_fg_config(struct smb1360_chip *chip) } /* Update CC to SOC COEFF */ if (chip->cc_soc_coeff != -EINVAL) { reg2[1] = (chip->cc_soc_coeff & 0xFF00) >> 8; reg2[1] = (chip->cc_soc_coeff & 0xFF00) >> 8; reg2[0] = (chip->cc_soc_coeff & 0xFF); rc = smb1360_write_bytes(chip, CC_TO_SOC_COEFF, reg2, 2); rc = smb1360_write_bytes(chip, CC_TO_SOC_COEFF, reg2, 2); if (rc) { pr_err("Couldn't write cc_soc_coeff rc=%d\n", rc); goto disable_fg; } } } } /* Update cutoff voltage for SOC = 0 */ if (chip->v_cutoff_mv != -EINVAL) { temp = (u16) div_u64(chip->v_cutoff_mv * 0x7FFF, 5000); reg2[1] = (temp & 0xFF00) >> 8; reg2[0] = temp & 0xFF; rc = smb1360_write_bytes(chip, FG_SYS_CUTOFF_V_REG, reg2, 2); if (rc) { pr_err("Couldn't write cutoff_mv rc=%d\n", rc); goto disable_fg; } } /* * Update FG iterm for SOC = 100, this value is always assumed * to be -ve */ if (chip->fg_iterm_ma != -EINVAL) { int iterm = chip->fg_iterm_ma * -1; temp = (s16) div_s64(iterm * 0x7FFF, 2500); reg2[1] = (temp & 0xFF00) >> 8; reg2[0] = temp & 0xFF; rc = smb1360_write_bytes(chip, FG_ITERM_REG, reg2, 2); if (rc) { pr_err("Couldn't write fg_iterm rc=%d\n", rc); goto disable_fg; } } /* * Update FG iterm standby for SOC = 0, this value is always * assumed to be +ve */ if (chip->fg_ibatt_standby_ma != -EINVAL) { int iterm = chip->fg_ibatt_standby_ma; temp = (u16) div_u64(iterm * 0x7FFF, 2500); reg2[1] = (temp & 0xFF00) >> 8; reg2[0] = temp & 0xFF; rc = smb1360_write_bytes(chip, FG_IBATT_STANDBY_REG, reg2, 2); if (rc) { pr_err("Couldn't write fg_iterm rc=%d\n", rc); goto disable_fg; } } disable_fg: /* disable FG access */ smb1360_disable_fg_access(chip); Loading Loading @@ -3091,6 +3154,21 @@ static int smb_parse_dt(struct smb1360_chip *chip) if (rc < 0) chip->cc_soc_coeff = -EINVAL; rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage-mv", &chip->v_cutoff_mv); if (rc < 0) chip->v_cutoff_mv = -EINVAL; rc = of_property_read_u32(node, "qcom,fg-iterm-ma", &chip->fg_iterm_ma); if (rc < 0) chip->fg_iterm_ma = -EINVAL; rc = of_property_read_u32(node, "qcom,fg-ibatt-standby-ma", &chip->fg_ibatt_standby_ma); if (rc < 0) chip->fg_ibatt_standby_ma = -EINVAL; return 0; } Loading Loading
Documentation/devicetree/bindings/power/smb1360-charger-fg.txt +15 −1 Original line number Diff line number Diff line Loading @@ -79,6 +79,16 @@ Optional Properties: is specified. This value is calculated from the batt-capacity and then encoded as floating number. cc_soc_coeff = HALF_ENCODING(8192 / batt-capacity) - qcom,fg-cutoff-voltage-mv This is the minimum allowed system voltage. The FG will report SOC = 0 at this volatge. This value is in mv. - qcom,fg-iterm-ma This is termination current at which the Monotonic SOC reports 100. The value passed here is negated in the driver (assuming that the iterm is always -ve). This value is in mA. - qcom,fg-ibatt-standby-ma This is the minimum current value for the SOC to be above 0% at the cutoff voltage. This value is in mA. Example: i2c@f9967000 { Loading @@ -100,7 +110,11 @@ Example: /* battery capacity */ qcom,fg-batt-capacity-mah = <4000>; qcom,fg-cc-soc-coeff = <0x8009> qcom,fg-cc-soc-coeff = <0x8009>; qcom,fg-cutoff-voltage-mv = <3300>; qcom,fg-iterm-ma = <100>; qcom,fg-ibatt-standby-ma = <200>; qcom,float-voltage-mv = <4200>; qcom,iterm-ma = <100>; Loading
drivers/power/smb1360-charger-fg.c +105 −27 Original line number Diff line number Diff line Loading @@ -199,6 +199,9 @@ #define CC_TO_SOC_COEFF 0xBA #define ACTUAL_CAPACITY_REG 0xBE #define FG_SYS_CUTOFF_V_REG 0xD3 #define FG_ITERM_REG 0xD9 #define FG_IBATT_STANDBY_REG 0xCF #define FG_I2C_CFG_MASK SMB1360_MASK(2, 1) #define FG_CFG_I2C_ADDR 0x2 Loading Loading @@ -272,6 +275,9 @@ struct smb1360_chip { int voltage_empty_mv; int batt_capacity_mah; int cc_soc_coeff; int v_cutoff_mv; int fg_iterm_ma; int fg_ibatt_standby_ma; /* status tracking */ bool usb_present; Loading Loading @@ -2512,29 +2518,36 @@ static int smb1360_fg_config(struct smb1360_chip *chip) } /* scratch-pad register config */ if (chip->batt_capacity_mah != -EINVAL) { if (chip->batt_capacity_mah != -EINVAL || chip->v_cutoff_mv != -EINVAL || chip->fg_iterm_ma != -EINVAL || chip->fg_ibatt_standby_ma != -EINVAL) { rc = smb1360_enable_fg_access(chip); if (rc) { pr_err("Couldn't enable FG access rc=%d\n", rc); return rc; } /* Update battery capacity */ if (chip->batt_capacity_mah != -EINVAL) { rc = smb1360_read_bytes(chip, ACTUAL_CAPACITY_REG, reg2, 2); if (rc) { pr_err("Failed to read NOM CAPACITY rc=%d\n", pr_err("Failed to read ACTUAL CAPACITY rc=%d\n", rc); goto disable_fg; } fcc_mah = (reg2[1] << 8) | reg2[0]; if (fcc_mah == chip->batt_capacity_mah) { pr_debug("battery capacity correct\n"); goto disable_fg; } } else { /* Update the battery capacity */ reg2[1] = (chip->batt_capacity_mah & 0xFF00) >> 8; reg2[1] = (chip->batt_capacity_mah & 0xFF00) >> 8; reg2[0] = (chip->batt_capacity_mah & 0xFF); rc = smb1360_write_bytes(chip, ACTUAL_CAPACITY_REG, reg2, 2); rc = smb1360_write_bytes(chip, ACTUAL_CAPACITY_REG, reg2, 2); if (rc) { pr_err("Couldn't write batt-capacity rc=%d\n", rc); Loading @@ -2542,16 +2555,66 @@ static int smb1360_fg_config(struct smb1360_chip *chip) } /* Update CC to SOC COEFF */ if (chip->cc_soc_coeff != -EINVAL) { reg2[1] = (chip->cc_soc_coeff & 0xFF00) >> 8; reg2[1] = (chip->cc_soc_coeff & 0xFF00) >> 8; reg2[0] = (chip->cc_soc_coeff & 0xFF); rc = smb1360_write_bytes(chip, CC_TO_SOC_COEFF, reg2, 2); rc = smb1360_write_bytes(chip, CC_TO_SOC_COEFF, reg2, 2); if (rc) { pr_err("Couldn't write cc_soc_coeff rc=%d\n", rc); goto disable_fg; } } } } /* Update cutoff voltage for SOC = 0 */ if (chip->v_cutoff_mv != -EINVAL) { temp = (u16) div_u64(chip->v_cutoff_mv * 0x7FFF, 5000); reg2[1] = (temp & 0xFF00) >> 8; reg2[0] = temp & 0xFF; rc = smb1360_write_bytes(chip, FG_SYS_CUTOFF_V_REG, reg2, 2); if (rc) { pr_err("Couldn't write cutoff_mv rc=%d\n", rc); goto disable_fg; } } /* * Update FG iterm for SOC = 100, this value is always assumed * to be -ve */ if (chip->fg_iterm_ma != -EINVAL) { int iterm = chip->fg_iterm_ma * -1; temp = (s16) div_s64(iterm * 0x7FFF, 2500); reg2[1] = (temp & 0xFF00) >> 8; reg2[0] = temp & 0xFF; rc = smb1360_write_bytes(chip, FG_ITERM_REG, reg2, 2); if (rc) { pr_err("Couldn't write fg_iterm rc=%d\n", rc); goto disable_fg; } } /* * Update FG iterm standby for SOC = 0, this value is always * assumed to be +ve */ if (chip->fg_ibatt_standby_ma != -EINVAL) { int iterm = chip->fg_ibatt_standby_ma; temp = (u16) div_u64(iterm * 0x7FFF, 2500); reg2[1] = (temp & 0xFF00) >> 8; reg2[0] = temp & 0xFF; rc = smb1360_write_bytes(chip, FG_IBATT_STANDBY_REG, reg2, 2); if (rc) { pr_err("Couldn't write fg_iterm rc=%d\n", rc); goto disable_fg; } } disable_fg: /* disable FG access */ smb1360_disable_fg_access(chip); Loading Loading @@ -3091,6 +3154,21 @@ static int smb_parse_dt(struct smb1360_chip *chip) if (rc < 0) chip->cc_soc_coeff = -EINVAL; rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage-mv", &chip->v_cutoff_mv); if (rc < 0) chip->v_cutoff_mv = -EINVAL; rc = of_property_read_u32(node, "qcom,fg-iterm-ma", &chip->fg_iterm_ma); if (rc < 0) chip->fg_iterm_ma = -EINVAL; rc = of_property_read_u32(node, "qcom,fg-ibatt-standby-ma", &chip->fg_ibatt_standby_ma); if (rc < 0) chip->fg_ibatt_standby_ma = -EINVAL; return 0; } Loading