Loading drivers/power/supply/qcom/fg-core.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -522,4 +522,5 @@ extern void fg_circ_buf_clr(struct fg_circ_buf *); extern int fg_circ_buf_avg(struct fg_circ_buf *, int *); extern int fg_circ_buf_median(struct fg_circ_buf *, int *); extern int fg_lerp(const struct fg_pt *, size_t, s32, s32 *); extern int fg_dma_mem_req(struct fg_chip *, bool); #endif drivers/power/supply/qcom/fg-memif.c +59 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -746,6 +746,64 @@ out: return rc; } int fg_dma_mem_req(struct fg_chip *chip, bool request) { int ret, rc = 0, retry_count = RETRY_COUNT; u8 val; if (request) { /* configure for DMA access */ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, MEM_ACCESS_REQ_BIT); if (rc < 0) { pr_err("failed to set mem_access bit rc=%d\n", rc); return rc; } rc = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip), MEM_IF_ARB_REQ_BIT, MEM_IF_ARB_REQ_BIT); if (rc < 0) { pr_err("failed to set mem_arb bit rc=%d\n", rc); goto release_mem; } while (retry_count--) { rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &val, 1); if (rc < 0) { pr_err("failed to set ima_rt_sts rc=%d\n", rc); goto release_mem; } if (val & MEM_GNT_BIT) break; msleep(20); } if (!retry_count && !(val & MEM_GNT_BIT)) { pr_err("failed to get memory access\n"); rc = -ETIMEDOUT; goto release_mem; } return 0; } release_mem: /* Release access */ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0); if (rc < 0) pr_err("failed to reset mem_access bit rc = %d\n", rc); ret = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip), MEM_IF_ARB_REQ_BIT, 0); if (ret < 0) { pr_err("failed to release mem_arb bit rc=%d\n", ret); return ret; } return rc; } int fg_ima_init(struct fg_chip *chip) { int rc; Loading drivers/power/supply/qcom/fg-reg.h +15 −2 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -29,6 +29,7 @@ #define BATT_SOC_STS_CLR(chip) (chip->batt_soc_base + 0x4A) #define BATT_SOC_LOW_PWR_CFG(chip) (chip->batt_soc_base + 0x52) #define BATT_SOC_LOW_PWR_STS(chip) (chip->batt_soc_base + 0x56) #define BATT_SOC_RST_CTRL0(chip) (chip->batt_soc_base + 0xBA) /* BATT_SOC_INT_RT_STS */ #define MSOC_EMPTY_BIT BIT(5) Loading @@ -39,6 +40,9 @@ /* BATT_SOC_RESTART */ #define RESTART_GO_BIT BIT(0) /* BCL_RESET */ #define BCL_RESET_BIT BIT(2) /* FG_BATT_INFO register definitions */ #define BATT_INFO_BATT_TEMP_STS(chip) (chip->batt_info_base + 0x06) #define BATT_INFO_SYS_BATT(chip) (chip->batt_info_base + 0x07) Loading @@ -58,7 +62,6 @@ #define BATT_INFO_JEITA_COLD(chip) (chip->batt_info_base + 0x63) #define BATT_INFO_JEITA_HOT(chip) (chip->batt_info_base + 0x64) #define BATT_INFO_JEITA_TOO_HOT(chip) (chip->batt_info_base + 0x65) /* only for v1.1 */ #define BATT_INFO_ESR_CFG(chip) (chip->batt_info_base + 0x69) /* starting from v2.0 */ Loading Loading @@ -95,6 +98,8 @@ #define BATT_INFO_IADC_MSB(chip) (chip->batt_info_base + 0xAF) #define BATT_INFO_TM_MISC(chip) (chip->batt_info_base + 0xE5) #define BATT_INFO_TM_MISC1(chip) (chip->batt_info_base + 0xE6) #define BATT_INFO_PEEK_MUX1(chip) (chip->batt_info_base + 0xEB) #define BATT_INFO_RDBACK(chip) (chip->batt_info_base + 0xEF) /* BATT_INFO_BATT_TEMP_STS */ #define JEITA_TOO_HOT_STS_BIT BIT(7) Loading Loading @@ -264,8 +269,12 @@ #define ESR_REQ_CTL_BIT BIT(1) #define ESR_REQ_CTL_EN_BIT BIT(0) /* BATT_INFO_PEEK_MUX1 */ #define PEEK_MUX1_BIT BIT(0) /* FG_MEM_IF register and bit definitions */ #define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10) #define MEM_IF_MEM_ARB_CFG(chip) ((chip->mem_if_base) + 0x40) #define MEM_IF_MEM_INTF_CFG(chip) ((chip->mem_if_base) + 0x50) #define MEM_IF_IMA_CTL(chip) ((chip->mem_if_base) + 0x51) #define MEM_IF_IMA_CFG(chip) ((chip->mem_if_base) + 0x52) Loading @@ -286,6 +295,7 @@ /* MEM_IF_INT_RT_STS */ #define MEM_XCP_BIT BIT(1) #define MEM_GNT_BIT BIT(2) /* MEM_IF_MEM_INTF_CFG */ #define MEM_ACCESS_REQ_BIT BIT(7) Loading Loading @@ -326,4 +336,7 @@ /* MEM_IF_DMA_CTL */ #define DMA_CLEAR_LOG_BIT BIT(0) /* MEM_IF_REQ */ #define MEM_IF_ARB_REQ_BIT BIT(0) #endif drivers/power/supply/qcom/fg-util.c +3 −3 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -420,7 +420,7 @@ int fg_write(struct fg_chip *chip, int addr, u8 *val, int len) return -ENXIO; mutex_lock(&chip->bus_lock); sec_access = (addr & 0x00FF) > 0xD0; sec_access = (addr & 0x00FF) >= 0xBA; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); if (rc < 0) { Loading Loading @@ -460,7 +460,7 @@ int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val) return -ENXIO; mutex_lock(&chip->bus_lock); sec_access = (addr & 0x00FF) > 0xD0; sec_access = (addr & 0x00FF) >= 0xBA; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); if (rc < 0) { Loading drivers/power/supply/qcom/qpnp-fg-gen3.c +105 −0 Original line number Diff line number Diff line Loading @@ -3850,6 +3850,9 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CC_STEP_SEL: pval->intval = chip->ttf.cc_step.sel; break; case POWER_SUPPLY_PROP_FG_RESET_CLOCK: pval->intval = 0; break; default: pr_err("unsupported property %d\n", psp); rc = -EINVAL; Loading @@ -3862,6 +3865,100 @@ static int fg_psy_get_property(struct power_supply *psy, return 0; } #define BCL_RESET_RETRY_COUNT 4 static int fg_bcl_reset(struct fg_chip *chip) { int i, ret, rc = 0; u8 val, peek_mux; bool success = false; /* Read initial value of peek mux1 */ rc = fg_read(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1); if (rc < 0) { pr_err("Error in writing peek mux1, rc=%d\n", rc); return rc; } val = 0x83; rc = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &val, 1); if (rc < 0) { pr_err("Error in writing peek mux1, rc=%d\n", rc); return rc; } mutex_lock(&chip->sram_rw_lock); for (i = 0; i < BCL_RESET_RETRY_COUNT; i++) { rc = fg_dma_mem_req(chip, true); if (rc < 0) { pr_err("Error in locking memory, rc=%d\n", rc); goto unlock; } rc = fg_read(chip, BATT_INFO_RDBACK(chip), &val, 1); if (rc < 0) { pr_err("Error in reading rdback, rc=%d\n", rc); goto release_mem; } if (val & PEEK_MUX1_BIT) { rc = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip), BCL_RESET_BIT, BCL_RESET_BIT); if (rc < 0) { pr_err("Error in writing RST_CTRL0, rc=%d\n", rc); goto release_mem; } rc = fg_dma_mem_req(chip, false); if (rc < 0) pr_err("Error in unlocking memory, rc=%d\n", rc); /* Delay of 2ms */ usleep_range(2000, 3000); ret = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip), BCL_RESET_BIT, 0); if (ret < 0) pr_err("Error in writing RST_CTRL0, rc=%d\n", rc); if (!rc && !ret) success = true; goto unlock; } else { rc = fg_dma_mem_req(chip, false); if (rc < 0) { pr_err("Error in unlocking memory, rc=%d\n", rc); goto unlock; } success = false; pr_err_ratelimited("PEEK_MUX1 not set retrying...\n"); msleep(1000); } } release_mem: rc = fg_dma_mem_req(chip, false); if (rc < 0) pr_err("Error in unlocking memory, rc=%d\n", rc); unlock: ret = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1); if (ret < 0) { pr_err("Error in writing peek mux1, rc=%d\n", rc); mutex_unlock(&chip->sram_rw_lock); return ret; } mutex_unlock(&chip->sram_rw_lock); if (!success) return -EAGAIN; else return rc; } static int fg_psy_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *pval) Loading Loading @@ -3950,6 +4047,13 @@ static int fg_psy_set_property(struct power_supply *psy, return rc; } break; case POWER_SUPPLY_PROP_FG_RESET_CLOCK: rc = fg_bcl_reset(chip); if (rc < 0) { pr_err("Error in resetting BCL clock, rc=%d\n", rc); return rc; } break; default: break; } Loading Loading @@ -4047,6 +4151,7 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, POWER_SUPPLY_PROP_CC_STEP, POWER_SUPPLY_PROP_CC_STEP_SEL, POWER_SUPPLY_PROP_FG_RESET_CLOCK, }; static const struct power_supply_desc fg_psy_desc = { Loading Loading
drivers/power/supply/qcom/fg-core.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -522,4 +522,5 @@ extern void fg_circ_buf_clr(struct fg_circ_buf *); extern int fg_circ_buf_avg(struct fg_circ_buf *, int *); extern int fg_circ_buf_median(struct fg_circ_buf *, int *); extern int fg_lerp(const struct fg_pt *, size_t, s32, s32 *); extern int fg_dma_mem_req(struct fg_chip *, bool); #endif
drivers/power/supply/qcom/fg-memif.c +59 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -746,6 +746,64 @@ out: return rc; } int fg_dma_mem_req(struct fg_chip *chip, bool request) { int ret, rc = 0, retry_count = RETRY_COUNT; u8 val; if (request) { /* configure for DMA access */ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, MEM_ACCESS_REQ_BIT); if (rc < 0) { pr_err("failed to set mem_access bit rc=%d\n", rc); return rc; } rc = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip), MEM_IF_ARB_REQ_BIT, MEM_IF_ARB_REQ_BIT); if (rc < 0) { pr_err("failed to set mem_arb bit rc=%d\n", rc); goto release_mem; } while (retry_count--) { rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &val, 1); if (rc < 0) { pr_err("failed to set ima_rt_sts rc=%d\n", rc); goto release_mem; } if (val & MEM_GNT_BIT) break; msleep(20); } if (!retry_count && !(val & MEM_GNT_BIT)) { pr_err("failed to get memory access\n"); rc = -ETIMEDOUT; goto release_mem; } return 0; } release_mem: /* Release access */ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0); if (rc < 0) pr_err("failed to reset mem_access bit rc = %d\n", rc); ret = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip), MEM_IF_ARB_REQ_BIT, 0); if (ret < 0) { pr_err("failed to release mem_arb bit rc=%d\n", ret); return ret; } return rc; } int fg_ima_init(struct fg_chip *chip) { int rc; Loading
drivers/power/supply/qcom/fg-reg.h +15 −2 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -29,6 +29,7 @@ #define BATT_SOC_STS_CLR(chip) (chip->batt_soc_base + 0x4A) #define BATT_SOC_LOW_PWR_CFG(chip) (chip->batt_soc_base + 0x52) #define BATT_SOC_LOW_PWR_STS(chip) (chip->batt_soc_base + 0x56) #define BATT_SOC_RST_CTRL0(chip) (chip->batt_soc_base + 0xBA) /* BATT_SOC_INT_RT_STS */ #define MSOC_EMPTY_BIT BIT(5) Loading @@ -39,6 +40,9 @@ /* BATT_SOC_RESTART */ #define RESTART_GO_BIT BIT(0) /* BCL_RESET */ #define BCL_RESET_BIT BIT(2) /* FG_BATT_INFO register definitions */ #define BATT_INFO_BATT_TEMP_STS(chip) (chip->batt_info_base + 0x06) #define BATT_INFO_SYS_BATT(chip) (chip->batt_info_base + 0x07) Loading @@ -58,7 +62,6 @@ #define BATT_INFO_JEITA_COLD(chip) (chip->batt_info_base + 0x63) #define BATT_INFO_JEITA_HOT(chip) (chip->batt_info_base + 0x64) #define BATT_INFO_JEITA_TOO_HOT(chip) (chip->batt_info_base + 0x65) /* only for v1.1 */ #define BATT_INFO_ESR_CFG(chip) (chip->batt_info_base + 0x69) /* starting from v2.0 */ Loading Loading @@ -95,6 +98,8 @@ #define BATT_INFO_IADC_MSB(chip) (chip->batt_info_base + 0xAF) #define BATT_INFO_TM_MISC(chip) (chip->batt_info_base + 0xE5) #define BATT_INFO_TM_MISC1(chip) (chip->batt_info_base + 0xE6) #define BATT_INFO_PEEK_MUX1(chip) (chip->batt_info_base + 0xEB) #define BATT_INFO_RDBACK(chip) (chip->batt_info_base + 0xEF) /* BATT_INFO_BATT_TEMP_STS */ #define JEITA_TOO_HOT_STS_BIT BIT(7) Loading Loading @@ -264,8 +269,12 @@ #define ESR_REQ_CTL_BIT BIT(1) #define ESR_REQ_CTL_EN_BIT BIT(0) /* BATT_INFO_PEEK_MUX1 */ #define PEEK_MUX1_BIT BIT(0) /* FG_MEM_IF register and bit definitions */ #define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10) #define MEM_IF_MEM_ARB_CFG(chip) ((chip->mem_if_base) + 0x40) #define MEM_IF_MEM_INTF_CFG(chip) ((chip->mem_if_base) + 0x50) #define MEM_IF_IMA_CTL(chip) ((chip->mem_if_base) + 0x51) #define MEM_IF_IMA_CFG(chip) ((chip->mem_if_base) + 0x52) Loading @@ -286,6 +295,7 @@ /* MEM_IF_INT_RT_STS */ #define MEM_XCP_BIT BIT(1) #define MEM_GNT_BIT BIT(2) /* MEM_IF_MEM_INTF_CFG */ #define MEM_ACCESS_REQ_BIT BIT(7) Loading Loading @@ -326,4 +336,7 @@ /* MEM_IF_DMA_CTL */ #define DMA_CLEAR_LOG_BIT BIT(0) /* MEM_IF_REQ */ #define MEM_IF_ARB_REQ_BIT BIT(0) #endif
drivers/power/supply/qcom/fg-util.c +3 −3 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -420,7 +420,7 @@ int fg_write(struct fg_chip *chip, int addr, u8 *val, int len) return -ENXIO; mutex_lock(&chip->bus_lock); sec_access = (addr & 0x00FF) > 0xD0; sec_access = (addr & 0x00FF) >= 0xBA; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); if (rc < 0) { Loading Loading @@ -460,7 +460,7 @@ int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val) return -ENXIO; mutex_lock(&chip->bus_lock); sec_access = (addr & 0x00FF) > 0xD0; sec_access = (addr & 0x00FF) >= 0xBA; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); if (rc < 0) { Loading
drivers/power/supply/qcom/qpnp-fg-gen3.c +105 −0 Original line number Diff line number Diff line Loading @@ -3850,6 +3850,9 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CC_STEP_SEL: pval->intval = chip->ttf.cc_step.sel; break; case POWER_SUPPLY_PROP_FG_RESET_CLOCK: pval->intval = 0; break; default: pr_err("unsupported property %d\n", psp); rc = -EINVAL; Loading @@ -3862,6 +3865,100 @@ static int fg_psy_get_property(struct power_supply *psy, return 0; } #define BCL_RESET_RETRY_COUNT 4 static int fg_bcl_reset(struct fg_chip *chip) { int i, ret, rc = 0; u8 val, peek_mux; bool success = false; /* Read initial value of peek mux1 */ rc = fg_read(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1); if (rc < 0) { pr_err("Error in writing peek mux1, rc=%d\n", rc); return rc; } val = 0x83; rc = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &val, 1); if (rc < 0) { pr_err("Error in writing peek mux1, rc=%d\n", rc); return rc; } mutex_lock(&chip->sram_rw_lock); for (i = 0; i < BCL_RESET_RETRY_COUNT; i++) { rc = fg_dma_mem_req(chip, true); if (rc < 0) { pr_err("Error in locking memory, rc=%d\n", rc); goto unlock; } rc = fg_read(chip, BATT_INFO_RDBACK(chip), &val, 1); if (rc < 0) { pr_err("Error in reading rdback, rc=%d\n", rc); goto release_mem; } if (val & PEEK_MUX1_BIT) { rc = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip), BCL_RESET_BIT, BCL_RESET_BIT); if (rc < 0) { pr_err("Error in writing RST_CTRL0, rc=%d\n", rc); goto release_mem; } rc = fg_dma_mem_req(chip, false); if (rc < 0) pr_err("Error in unlocking memory, rc=%d\n", rc); /* Delay of 2ms */ usleep_range(2000, 3000); ret = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip), BCL_RESET_BIT, 0); if (ret < 0) pr_err("Error in writing RST_CTRL0, rc=%d\n", rc); if (!rc && !ret) success = true; goto unlock; } else { rc = fg_dma_mem_req(chip, false); if (rc < 0) { pr_err("Error in unlocking memory, rc=%d\n", rc); goto unlock; } success = false; pr_err_ratelimited("PEEK_MUX1 not set retrying...\n"); msleep(1000); } } release_mem: rc = fg_dma_mem_req(chip, false); if (rc < 0) pr_err("Error in unlocking memory, rc=%d\n", rc); unlock: ret = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1); if (ret < 0) { pr_err("Error in writing peek mux1, rc=%d\n", rc); mutex_unlock(&chip->sram_rw_lock); return ret; } mutex_unlock(&chip->sram_rw_lock); if (!success) return -EAGAIN; else return rc; } static int fg_psy_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *pval) Loading Loading @@ -3950,6 +4047,13 @@ static int fg_psy_set_property(struct power_supply *psy, return rc; } break; case POWER_SUPPLY_PROP_FG_RESET_CLOCK: rc = fg_bcl_reset(chip); if (rc < 0) { pr_err("Error in resetting BCL clock, rc=%d\n", rc); return rc; } break; default: break; } Loading Loading @@ -4047,6 +4151,7 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, POWER_SUPPLY_PROP_CC_STEP, POWER_SUPPLY_PROP_CC_STEP_SEL, POWER_SUPPLY_PROP_FG_RESET_CLOCK, }; static const struct power_supply_desc fg_psy_desc = { Loading