Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +32 −0 Original line number Diff line number Diff line Loading @@ -229,6 +229,17 @@ First Level Node - FG Gen4 device This should be defined in the ascending order and in the range of 0-100. Array limit is set to 3. - qcom,ki-coeff-low-dischg Usage: optional Value type: <prop-encoded-array> Definition: Array of ki coefficient values for low discharge current during discharge. These values will be applied when the monotonic SOC goes below the SOC threshold specified under qcom,ki-coeff-soc-dischg. Array limit is set to 3. This property should be specified if qcom,ki-coeff-soc-dischg is specified to make it fully functional. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-med-dischg Usage: optional Value type: <prop-encoded-array> Loading @@ -251,6 +262,27 @@ First Level Node - FG Gen4 device is specified to make it fully functional. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-low-chg Usage: optional Value type: <u32> Definition: ki coefficient value for low charge current during charging. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-med-chg Usage: optional Value type: <u32> Definition: ki coefficient value for medium charge current during charging. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-hi-chg Usage: optional Value type: <u32> Definition: ki coefficient value for high charge current during charging. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,fg-rconn-uohms Usage: optional Value type: <u32> Loading drivers/power/supply/qcom/fg-core.h +4 −0 Original line number Diff line number Diff line Loading @@ -190,8 +190,12 @@ enum fg_sram_param_id { FG_SRAM_DELTA_BSOC_THR, FG_SRAM_RECHARGE_SOC_THR, FG_SRAM_RECHARGE_VBATT_THR, FG_SRAM_KI_COEFF_LOW_DISCHG, FG_SRAM_KI_COEFF_MED_DISCHG, FG_SRAM_KI_COEFF_HI_DISCHG, FG_SRAM_KI_COEFF_LOW_CHG, FG_SRAM_KI_COEFF_MED_CHG, FG_SRAM_KI_COEFF_HI_CHG, FG_SRAM_KI_COEFF_FULL_SOC, FG_SRAM_ESR_TIGHT_FILTER, FG_SRAM_ESR_BROAD_FILTER, Loading drivers/power/supply/qcom/fg-memif.c +51 −0 Original line number Diff line number Diff line Loading @@ -793,6 +793,37 @@ int fg_interleaved_mem_write(struct fg_dev *fg, u16 address, u8 offset, return rc; } static int fg_poll_alg_active(struct fg_dev *fg) { u32 retries = 35, poll_time_us = 10000; int rc; u8 val; /* * ALG active should be asserted low within ~164 ms mostly however * during ESR pulsing, a worst case delay of ~320 ms is needed. */ while (retries--) { rc = fg_read(fg, BATT_INFO_PEEK_RD(fg), &val, 1); if (rc < 0) { pr_err("failed to read PEEK_MUX rc=%d\n", rc); return rc; } if (!(val & ALG_ACTIVE_BIT)) break; usleep_range(poll_time_us, poll_time_us + 1); } if (val & ALG_ACTIVE_BIT) return -ETIMEDOUT; /* Wait for 1 ms after ALG active is asserted low */ usleep_range(1000, 1001); return rc; } static int fg_direct_mem_release(struct fg_dev *fg) { int rc; Loading Loading @@ -823,6 +854,14 @@ static int fg_direct_mem_request(struct fg_dev *fg) int rc, ret, i = 0; u8 val, mask, poll_bit; if (fg->wa_flags & PM8150B_V1_DMA_WA) { rc = fg_poll_alg_active(fg); if (rc < 0) { pr_err("Failed to assert ALG active rc=%d\n", rc); return rc; } } val = mask = MEM_ARB_REQ_BIT; rc = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), mask, val); if (rc < 0) { Loading Loading @@ -1169,6 +1208,7 @@ static struct fg_dma_address fg_gen4_addr_map[6] = { static int fg_dma_init(struct fg_dev *fg) { int rc; u8 val; if (fg->version == GEN3_FG) { fg->sram.addr_map = fg_gen3_addr_map; Loading Loading @@ -1217,6 +1257,17 @@ static int fg_dma_init(struct fg_dev *fg) return rc; } /* Configure PEEK_MUX only for PM8150B v1.0 */ if (fg->wa_flags & PM8150B_V1_DMA_WA) { val = ALG_ACTIVE_PEEK_CFG; rc = fg_write(fg, BATT_INFO_PEEK_MUX4(fg), &val, 1); if (rc < 0) { pr_err("failed to configure batt_info_peek_mux4 rc:%d\n", rc); return rc; } } return 0; } Loading drivers/power/supply/qcom/fg-reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -275,6 +275,12 @@ #define ESR_REQ_CTL_BIT BIT(1) #define ESR_REQ_CTL_EN_BIT BIT(0) #define BATT_INFO_PEEK_MUX4(chip) (chip->batt_info_base + 0xEE) #define ALG_ACTIVE_PEEK_CFG 0xAC #define BATT_INFO_PEEK_RD(chip) (chip->batt_info_base + 0xEF) #define ALG_ACTIVE_BIT BIT(3) /* FG_MEM_IF register and bit definitions */ #define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10) #define MEM_XCP_BIT BIT(1) Loading drivers/power/supply/qcom/fg-util.c +52 −18 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ CHARS_PER_ITEM) + 1) \ #define VOLTAGE_15BIT_MASK GENMASK(14, 0) #define MAX_READ_TRIES 5 int fg_decode_voltage_15b(struct fg_sram_param *sp, enum fg_sram_param_id id, int value) Loading Loading @@ -826,13 +827,12 @@ int fg_restart(struct fg_dev *fg, int wait_time_ms) /* All fg_get_* , fg_set_* functions here */ #define MAX_TRIES_SOC 5 int fg_get_msoc_raw(struct fg_dev *fg, int *val) { u8 cap[2]; int rc, tries = 0; while (tries < MAX_TRIES_SOC) { while (tries < MAX_READ_TRIES) { rc = fg_read(fg, BATT_SOC_FG_MONOTONIC_SOC(fg), cap, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", Loading @@ -846,8 +846,8 @@ int fg_get_msoc_raw(struct fg_dev *fg, int *val) tries++; } if (tries == MAX_TRIES_SOC) { pr_err("shadow registers do not match\n"); if (tries == MAX_READ_TRIES) { pr_err("MSOC: shadow registers do not match\n"); return -EINVAL; } Loading Loading @@ -934,10 +934,11 @@ int fg_get_battery_resistance(struct fg_dev *fg, int *val) #define BATT_CURRENT_DENR 1000 int fg_get_battery_current(struct fg_dev *fg, int *val) { int rc = 0; int rc = 0, tries = 0; int64_t temp = 0; u8 buf[2]; u8 buf[2], buf_cp[2]; while (tries++ < MAX_READ_TRIES) { rc = fg_read(fg, BATT_INFO_IBATT_LSB(fg), buf, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", Loading @@ -945,6 +946,22 @@ int fg_get_battery_current(struct fg_dev *fg, int *val) return rc; } rc = fg_read(fg, BATT_INFO_IBATT_LSB_CP(fg), buf_cp, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", BATT_INFO_IBATT_LSB_CP(fg), rc); return rc; } if (buf[0] == buf_cp[0] && buf[1] == buf_cp[1]) break; } if (tries == MAX_READ_TRIES) { pr_err("IBATT: shadow registers do not match\n"); return -EINVAL; } if (fg->wa_flags & PMI8998_V1_REV_WA) temp = buf[0] << 8 | buf[1]; else Loading @@ -961,10 +978,11 @@ int fg_get_battery_current(struct fg_dev *fg, int *val) #define BATT_VOLTAGE_DENR 1000 int fg_get_battery_voltage(struct fg_dev *fg, int *val) { int rc = 0; int rc = 0, tries = 0; u16 temp = 0; u8 buf[2]; u8 buf[2], buf_cp[2]; while (tries++ < MAX_READ_TRIES) { rc = fg_read(fg, BATT_INFO_VBATT_LSB(fg), buf, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", Loading @@ -972,6 +990,22 @@ int fg_get_battery_voltage(struct fg_dev *fg, int *val) return rc; } rc = fg_read(fg, BATT_INFO_VBATT_LSB_CP(fg), buf_cp, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", BATT_INFO_VBATT_LSB_CP(fg), rc); return rc; } if (buf[0] == buf_cp[0] && buf[1] == buf_cp[1]) break; } if (tries == MAX_READ_TRIES) { pr_err("VBATT: shadow registers do not match\n"); return -EINVAL; } if (fg->wa_flags & PMI8998_V1_REV_WA) temp = buf[0] << 8 | buf[1]; else Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +32 −0 Original line number Diff line number Diff line Loading @@ -229,6 +229,17 @@ First Level Node - FG Gen4 device This should be defined in the ascending order and in the range of 0-100. Array limit is set to 3. - qcom,ki-coeff-low-dischg Usage: optional Value type: <prop-encoded-array> Definition: Array of ki coefficient values for low discharge current during discharge. These values will be applied when the monotonic SOC goes below the SOC threshold specified under qcom,ki-coeff-soc-dischg. Array limit is set to 3. This property should be specified if qcom,ki-coeff-soc-dischg is specified to make it fully functional. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-med-dischg Usage: optional Value type: <prop-encoded-array> Loading @@ -251,6 +262,27 @@ First Level Node - FG Gen4 device is specified to make it fully functional. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-low-chg Usage: optional Value type: <u32> Definition: ki coefficient value for low charge current during charging. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-med-chg Usage: optional Value type: <u32> Definition: ki coefficient value for medium charge current during charging. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,ki-coeff-hi-chg Usage: optional Value type: <u32> Definition: ki coefficient value for high charge current during charging. Value has no unit. Allowed range is 62 to 15564 in micro units. - qcom,fg-rconn-uohms Usage: optional Value type: <u32> Loading
drivers/power/supply/qcom/fg-core.h +4 −0 Original line number Diff line number Diff line Loading @@ -190,8 +190,12 @@ enum fg_sram_param_id { FG_SRAM_DELTA_BSOC_THR, FG_SRAM_RECHARGE_SOC_THR, FG_SRAM_RECHARGE_VBATT_THR, FG_SRAM_KI_COEFF_LOW_DISCHG, FG_SRAM_KI_COEFF_MED_DISCHG, FG_SRAM_KI_COEFF_HI_DISCHG, FG_SRAM_KI_COEFF_LOW_CHG, FG_SRAM_KI_COEFF_MED_CHG, FG_SRAM_KI_COEFF_HI_CHG, FG_SRAM_KI_COEFF_FULL_SOC, FG_SRAM_ESR_TIGHT_FILTER, FG_SRAM_ESR_BROAD_FILTER, Loading
drivers/power/supply/qcom/fg-memif.c +51 −0 Original line number Diff line number Diff line Loading @@ -793,6 +793,37 @@ int fg_interleaved_mem_write(struct fg_dev *fg, u16 address, u8 offset, return rc; } static int fg_poll_alg_active(struct fg_dev *fg) { u32 retries = 35, poll_time_us = 10000; int rc; u8 val; /* * ALG active should be asserted low within ~164 ms mostly however * during ESR pulsing, a worst case delay of ~320 ms is needed. */ while (retries--) { rc = fg_read(fg, BATT_INFO_PEEK_RD(fg), &val, 1); if (rc < 0) { pr_err("failed to read PEEK_MUX rc=%d\n", rc); return rc; } if (!(val & ALG_ACTIVE_BIT)) break; usleep_range(poll_time_us, poll_time_us + 1); } if (val & ALG_ACTIVE_BIT) return -ETIMEDOUT; /* Wait for 1 ms after ALG active is asserted low */ usleep_range(1000, 1001); return rc; } static int fg_direct_mem_release(struct fg_dev *fg) { int rc; Loading Loading @@ -823,6 +854,14 @@ static int fg_direct_mem_request(struct fg_dev *fg) int rc, ret, i = 0; u8 val, mask, poll_bit; if (fg->wa_flags & PM8150B_V1_DMA_WA) { rc = fg_poll_alg_active(fg); if (rc < 0) { pr_err("Failed to assert ALG active rc=%d\n", rc); return rc; } } val = mask = MEM_ARB_REQ_BIT; rc = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), mask, val); if (rc < 0) { Loading Loading @@ -1169,6 +1208,7 @@ static struct fg_dma_address fg_gen4_addr_map[6] = { static int fg_dma_init(struct fg_dev *fg) { int rc; u8 val; if (fg->version == GEN3_FG) { fg->sram.addr_map = fg_gen3_addr_map; Loading Loading @@ -1217,6 +1257,17 @@ static int fg_dma_init(struct fg_dev *fg) return rc; } /* Configure PEEK_MUX only for PM8150B v1.0 */ if (fg->wa_flags & PM8150B_V1_DMA_WA) { val = ALG_ACTIVE_PEEK_CFG; rc = fg_write(fg, BATT_INFO_PEEK_MUX4(fg), &val, 1); if (rc < 0) { pr_err("failed to configure batt_info_peek_mux4 rc:%d\n", rc); return rc; } } return 0; } Loading
drivers/power/supply/qcom/fg-reg.h +6 −0 Original line number Diff line number Diff line Loading @@ -275,6 +275,12 @@ #define ESR_REQ_CTL_BIT BIT(1) #define ESR_REQ_CTL_EN_BIT BIT(0) #define BATT_INFO_PEEK_MUX4(chip) (chip->batt_info_base + 0xEE) #define ALG_ACTIVE_PEEK_CFG 0xAC #define BATT_INFO_PEEK_RD(chip) (chip->batt_info_base + 0xEF) #define ALG_ACTIVE_BIT BIT(3) /* FG_MEM_IF register and bit definitions */ #define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10) #define MEM_XCP_BIT BIT(1) Loading
drivers/power/supply/qcom/fg-util.c +52 −18 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ CHARS_PER_ITEM) + 1) \ #define VOLTAGE_15BIT_MASK GENMASK(14, 0) #define MAX_READ_TRIES 5 int fg_decode_voltage_15b(struct fg_sram_param *sp, enum fg_sram_param_id id, int value) Loading Loading @@ -826,13 +827,12 @@ int fg_restart(struct fg_dev *fg, int wait_time_ms) /* All fg_get_* , fg_set_* functions here */ #define MAX_TRIES_SOC 5 int fg_get_msoc_raw(struct fg_dev *fg, int *val) { u8 cap[2]; int rc, tries = 0; while (tries < MAX_TRIES_SOC) { while (tries < MAX_READ_TRIES) { rc = fg_read(fg, BATT_SOC_FG_MONOTONIC_SOC(fg), cap, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", Loading @@ -846,8 +846,8 @@ int fg_get_msoc_raw(struct fg_dev *fg, int *val) tries++; } if (tries == MAX_TRIES_SOC) { pr_err("shadow registers do not match\n"); if (tries == MAX_READ_TRIES) { pr_err("MSOC: shadow registers do not match\n"); return -EINVAL; } Loading Loading @@ -934,10 +934,11 @@ int fg_get_battery_resistance(struct fg_dev *fg, int *val) #define BATT_CURRENT_DENR 1000 int fg_get_battery_current(struct fg_dev *fg, int *val) { int rc = 0; int rc = 0, tries = 0; int64_t temp = 0; u8 buf[2]; u8 buf[2], buf_cp[2]; while (tries++ < MAX_READ_TRIES) { rc = fg_read(fg, BATT_INFO_IBATT_LSB(fg), buf, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", Loading @@ -945,6 +946,22 @@ int fg_get_battery_current(struct fg_dev *fg, int *val) return rc; } rc = fg_read(fg, BATT_INFO_IBATT_LSB_CP(fg), buf_cp, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", BATT_INFO_IBATT_LSB_CP(fg), rc); return rc; } if (buf[0] == buf_cp[0] && buf[1] == buf_cp[1]) break; } if (tries == MAX_READ_TRIES) { pr_err("IBATT: shadow registers do not match\n"); return -EINVAL; } if (fg->wa_flags & PMI8998_V1_REV_WA) temp = buf[0] << 8 | buf[1]; else Loading @@ -961,10 +978,11 @@ int fg_get_battery_current(struct fg_dev *fg, int *val) #define BATT_VOLTAGE_DENR 1000 int fg_get_battery_voltage(struct fg_dev *fg, int *val) { int rc = 0; int rc = 0, tries = 0; u16 temp = 0; u8 buf[2]; u8 buf[2], buf_cp[2]; while (tries++ < MAX_READ_TRIES) { rc = fg_read(fg, BATT_INFO_VBATT_LSB(fg), buf, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", Loading @@ -972,6 +990,22 @@ int fg_get_battery_voltage(struct fg_dev *fg, int *val) return rc; } rc = fg_read(fg, BATT_INFO_VBATT_LSB_CP(fg), buf_cp, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", BATT_INFO_VBATT_LSB_CP(fg), rc); return rc; } if (buf[0] == buf_cp[0] && buf[1] == buf_cp[1]) break; } if (tries == MAX_READ_TRIES) { pr_err("VBATT: shadow registers do not match\n"); return -EINVAL; } if (fg->wa_flags & PMI8998_V1_REV_WA) temp = buf[0] << 8 | buf[1]; else Loading