power: pmi8998_fg: Rename to qcom_fg and add support for PMI8994/6
This adds support for accessing SRAM. That includes requesting and releasing access to SRAM by setting some registers and handling the mem-avail IRQ, configuring access, and reading from/writing to it. Pre-gen3 fuel gauges require reading from SRAM to get voltage, current and temperature data. Getting capacity is identical to gen3. Tested on Xiaomi Mi Note 2 with PMI8996.
This commit is contained in:
parent
cf062a5c35
commit
f96cfaff29
4 changed files with 599 additions and 100 deletions
|
|
@ -934,13 +934,13 @@ config CHARGER_QCOM_SMB2
|
|||
Say Y or M here to enable reporting the charger status and rate on
|
||||
supported platforms such as Snapdragon 845 and 835 based phones.
|
||||
|
||||
config BATTERY_PMI8998_FG
|
||||
tristate "Qualcomm PMI8998 fuel gauge driver"
|
||||
config BATTERY_QCOM_FG
|
||||
tristate "Qualcomm PMIC fuel gauge driver"
|
||||
depends on MFD_SPMI_PMIC
|
||||
help
|
||||
Say Y here to enable the Qualcomm PMI8998 Fuel Gauge driver. This
|
||||
Say Y here to enable the Qualcomm PMIC Fuel Gauge driver. This
|
||||
adds support for battery fuel gauging and state of charge of
|
||||
battery connected tothe fuel gauge. The state of charge is
|
||||
battery connected to the fuel gauge. The state of charge is
|
||||
reported through a BMS power supply property and also sends
|
||||
uevents when the capacity is updated.
|
||||
|
||||
|
|
|
|||
|
|
@ -111,4 +111,4 @@ obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o
|
|||
obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
|
||||
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
|
||||
obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
|
||||
obj-$(CONFIG_BATTERY_PMI8998_FG) += pmi8998_fg.o
|
||||
obj-$(CONFIG_BATTERY_QCOM_FG) += qcom_fg.o
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/device.h>
|
||||
|
|
@ -14,14 +15,14 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "pmi8998_fg.h"
|
||||
#include "qcom_fg.h"
|
||||
|
||||
/************************
|
||||
* IO FUNCTIONS
|
||||
* **********************/
|
||||
|
||||
/**
|
||||
* pmi8998_read() - Read multiple registers with regmap_bulk_read
|
||||
* qcom_fg_read() - Read multiple registers with regmap_bulk_read
|
||||
*
|
||||
* @param map The regmap to read
|
||||
* @param val Pointer to read values into
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
* @param len Number of registers (bytes) to read
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int pmi8998_read(struct regmap *map, u8 *val, u16 addr, int len)
|
||||
static int qcom_fg_read(struct regmap *map, u8 *val, u16 addr, int len)
|
||||
{
|
||||
if ((addr & 0xff00) == 0) {
|
||||
pr_err("base cannot be zero base=0x%02x\n", addr);
|
||||
|
|
@ -42,7 +43,7 @@ static int pmi8998_read(struct regmap *map, u8 *val, u16 addr, int len)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief pmi8998_write() - Write multiple registers with regmap_bulk_write
|
||||
* @brief qcom_fg_write() - Write multiple registers with regmap_bulk_write
|
||||
*
|
||||
* @param map The regmap to write
|
||||
* @param val Pointer to write values into
|
||||
|
|
@ -50,7 +51,7 @@ static int pmi8998_read(struct regmap *map, u8 *val, u16 addr, int len)
|
|||
* @param len Number of registers (bytes) to write
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int pmi8998_write(struct regmap *map, u8 *val, u16 addr, int len)
|
||||
static int qcom_fg_write(struct regmap *map, u8 *val, u16 addr, int len)
|
||||
{
|
||||
int rc;
|
||||
bool sec_access = (addr & 0xff) > 0xd0;
|
||||
|
|
@ -71,7 +72,7 @@ static int pmi8998_write(struct regmap *map, u8 *val, u16 addr, int len)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief pmi8998_masked_write() - like pmi8998_write but applies
|
||||
* @brief qcom_fg_masked_write() - like qcom_fg_write but applies
|
||||
* a mask first.
|
||||
*
|
||||
* @param map The regmap to write
|
||||
|
|
@ -80,19 +81,19 @@ static int pmi8998_write(struct regmap *map, u8 *val, u16 addr, int len)
|
|||
* @param len Number of registers (bytes) to write
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int pmi8998_masked_write(struct regmap *map, u16 addr,
|
||||
static int qcom_fg_masked_write(struct regmap *map, u16 addr,
|
||||
u8 mask, u8 val)
|
||||
{
|
||||
int error;
|
||||
u8 reg;
|
||||
error = pmi8998_read(map, ®, addr, 1);
|
||||
error = qcom_fg_read(map, ®, addr, 1);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
reg &= ~mask;
|
||||
reg |= val & mask;
|
||||
|
||||
error = pmi8998_write(map, ®, addr, 1);
|
||||
error = qcom_fg_write(map, ®, addr, 1);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -111,14 +112,243 @@ static int64_t twos_compliment_extend(int64_t val, int nbytes)
|
|||
return val;
|
||||
}
|
||||
|
||||
/************************
|
||||
* SRAM FUNCTIONS
|
||||
* **********************/
|
||||
|
||||
/**
|
||||
* qcom_fg_sram_check_access() - Check if SRAM is accessible
|
||||
*
|
||||
* @param chip Pointer to chip
|
||||
* @return bool true if accessible, false otherwise
|
||||
*/
|
||||
static bool qcom_fg_sram_check_access(struct qcom_fg_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
u8 mem_if_status;
|
||||
|
||||
rc = qcom_fg_read(chip->regmap, &mem_if_status,
|
||||
REG_MEM + MEM_INTF_STS, 1);
|
||||
|
||||
if(!(mem_if_status & MEM_INTF_AVAIL))
|
||||
return false;
|
||||
|
||||
rc = qcom_fg_read(chip->regmap, &mem_if_status,
|
||||
REG_MEM + MEM_INTF_CFG, 1);
|
||||
|
||||
if(rc)
|
||||
return false;
|
||||
|
||||
return !!(mem_if_status & RIF_MEM_ACCESS_REQ);
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_fg_sram_request_access() - Request access to SRAM and wait for it
|
||||
*
|
||||
* @param chip Pointer to chip
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int qcom_fg_sram_request_access(struct qcom_fg_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if(!qcom_fg_sram_check_access(chip)) {
|
||||
rc = qcom_fg_masked_write(chip->regmap, REG_MEM + MEM_INTF_CFG,
|
||||
RIF_MEM_ACCESS_REQ, RIF_MEM_ACCESS_REQ);
|
||||
if (rc) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to set SRAM access request bit: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait to get access to SRAM, and try again if interrupted */
|
||||
do {
|
||||
rc = wait_for_completion_interruptible_timeout(
|
||||
&chip->sram_access_granted,
|
||||
msecs_to_jiffies(MEM_IF_TIMEOUT_MS));
|
||||
} while(rc == -ERESTARTSYS);
|
||||
|
||||
if(rc <= 0) {
|
||||
rc = -ETIMEDOUT;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_fg_sram_release_access() - Release access to SRAM
|
||||
*
|
||||
* @param chip Pointer to chip
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int qcom_fg_sram_release_access(struct qcom_fg_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = qcom_fg_masked_write(chip->regmap, REG_MEM + MEM_INTF_CFG,
|
||||
RIF_MEM_ACCESS_REQ, 0);
|
||||
if (rc) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to set SRAM access request bit: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
reinit_completion(&chip->sram_access_granted);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_fg_sram_config_access() - Configure access to SRAM
|
||||
*
|
||||
* @param chip Pointer to chip
|
||||
* @param write 0 for read access, 1 for write access
|
||||
* @param burst 1 to access mutliple addresses successively
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int qcom_fg_sram_config_access(struct qcom_fg_chip *chip,
|
||||
bool write, bool burst)
|
||||
{
|
||||
int rc;
|
||||
u8 intf_ctl = (write ? MEM_INTF_CTL_WR_EN : 0)
|
||||
| (burst ? MEM_INTF_CTL_BURST : 0);
|
||||
|
||||
rc = qcom_fg_write(chip->regmap, &intf_ctl,
|
||||
REG_MEM + MEM_INTF_CTL, 1);
|
||||
|
||||
if(rc)
|
||||
dev_err(chip->dev,
|
||||
"Failed to configure SRAM access: %d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_fg_sram_read() - Read data from SRAM
|
||||
*
|
||||
* @param chip Pointer to chip
|
||||
* @param val Pointer to read values into
|
||||
* @param addr Address to read from
|
||||
* @param len Number of bytes to read
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int qcom_fg_sram_read(struct qcom_fg_chip *chip,
|
||||
u8 *val, u16 addr, int len, int offset)
|
||||
{
|
||||
int rc;
|
||||
u8 *rd_data = val;
|
||||
|
||||
rc = qcom_fg_sram_request_access(chip);
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to request SRAM access: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev,
|
||||
"Reading address 0x%x with offset %d of length %d from SRAM",
|
||||
addr, len, offset);
|
||||
|
||||
rc = qcom_fg_sram_config_access(chip, 0, (len > 4));
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to configure SRAM access: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
while(len > 0) {
|
||||
/* Set SRAM address register */
|
||||
rc = qcom_fg_write(chip->regmap, (u8 *) &addr,
|
||||
REG_MEM + MEM_INTF_ADDR_LSB, 2);
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to set SRAM address: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = qcom_fg_read(chip->regmap, rd_data,
|
||||
REG_MEM + MEM_INTF_RD_DATA0 + offset, len);
|
||||
|
||||
addr += 4;
|
||||
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
rd_data += 4 - offset;
|
||||
len -= 4 - offset;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
rc = qcom_fg_sram_release_access(chip);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_fg_sram_write() - Write data to SRAM
|
||||
*
|
||||
* @param chip Pointer to chip
|
||||
* @param val Pointer to write values into
|
||||
* @param addr Address to write to
|
||||
* @param len Number of bytes to write
|
||||
* @return int 0 on success, negative errno on error
|
||||
*/
|
||||
static int qcom_fg_sram_write(struct qcom_fg_chip *chip,
|
||||
u8 *val, u16 addr, int len, int offset)
|
||||
{
|
||||
int rc;
|
||||
u8 *wr_data = val;
|
||||
|
||||
rc = qcom_fg_sram_request_access(chip);
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to request SRAM access: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev,
|
||||
"Reading address 0x%x with offset %d of length %d from SRAM",
|
||||
addr, len, offset);
|
||||
|
||||
rc = qcom_fg_sram_config_access(chip, 1, (len > 4));
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to configure SRAM access: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
while(len > 0) {
|
||||
/* Set SRAM address register */
|
||||
rc = qcom_fg_write(chip->regmap, (u8 *) &addr,
|
||||
REG_MEM + MEM_INTF_ADDR_LSB, 2);
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to set SRAM address: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = qcom_fg_write(chip->regmap, wr_data,
|
||||
REG_MEM + MEM_INTF_WR_DATA0 + offset, len);
|
||||
|
||||
addr += 4;
|
||||
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
wr_data += 4 - offset;
|
||||
len -= 4 - offset;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
rc = qcom_fg_sram_release_access(chip);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Battery Status RW
|
||||
* ***********************/
|
||||
|
||||
static int pmi8998_fg_get_capacity(struct pmi8998_fg_chip *chip, int *val)
|
||||
static int qcom_fg_get_capacity(struct qcom_fg_chip *chip, int *val)
|
||||
{
|
||||
u8 cap[2];
|
||||
int error = pmi8998_read(chip->regmap, cap, REG_BASE + BATT_MONOTONIC_SOC, 2);
|
||||
int error = qcom_fg_read(chip->regmap, cap, REG_BASE + BATT_MONOTONIC_SOC, 2);
|
||||
if (error)
|
||||
return error;
|
||||
if (cap[0] != cap[1]) {
|
||||
|
|
@ -128,12 +358,66 @@ static int pmi8998_fg_get_capacity(struct pmi8998_fg_chip *chip, int *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pmi8998_fg_get_temperature(struct pmi8998_fg_chip *chip, int *val)
|
||||
static int qcom_fg_get_temperature(struct qcom_fg_chip *chip, int *val)
|
||||
{
|
||||
int rc, temp;
|
||||
u8 readval[2];
|
||||
|
||||
rc = pmi8998_read(chip->regmap, readval, REG_BATT + PARAM_ADDR_BATT_TEMP, 2);
|
||||
rc = qcom_fg_sram_read(chip, readval, 0x550, 2, 2);
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to read temperature: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
temp = readval[1] << 8 | readval[0];
|
||||
*val = temp * 625 / 1000 - 2730;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_fg_get_current(struct qcom_fg_chip *chip, int *val)
|
||||
{
|
||||
int rc, temp;
|
||||
u8 readval[2];
|
||||
|
||||
rc = qcom_fg_sram_read(chip, readval, 0x5CC, 2, 3);
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to read current: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
//handle rev 1 too
|
||||
temp = readval[1] << 8 | readval[0];
|
||||
temp = twos_compliment_extend(temp, 15);
|
||||
*val = div_s64((s64)temp * 152587, 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_fg_get_voltage(struct qcom_fg_chip *chip, int *val)
|
||||
{
|
||||
int rc, temp;
|
||||
u8 readval[2];
|
||||
|
||||
rc = qcom_fg_sram_read(chip, readval, 0x5CC, 2, 1);
|
||||
if(rc) {
|
||||
dev_err(chip->dev, "Failed to read voltage: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
temp = readval[1] << 8 | readval[0];
|
||||
*val = div_u64((u64)temp * 152587, 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Battery Status RW, Gen3
|
||||
* ***********************/
|
||||
|
||||
static int qcom_fg_gen3_get_temperature(struct qcom_fg_chip *chip, int *val)
|
||||
{
|
||||
int rc, temp;
|
||||
u8 readval[2];
|
||||
|
||||
rc = qcom_fg_read(chip->regmap, readval, REG_BATT + PARAM_ADDR_BATT_TEMP, 2);
|
||||
if (rc) {
|
||||
pr_err("Failed to read temperature\n");
|
||||
return rc;
|
||||
|
|
@ -146,12 +430,12 @@ static int pmi8998_fg_get_temperature(struct pmi8998_fg_chip *chip, int *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pmi8998_fg_get_current(struct pmi8998_fg_chip *chip, int *val)
|
||||
static int qcom_fg_gen3_get_current(struct qcom_fg_chip *chip, int *val)
|
||||
{
|
||||
int rc, temp;
|
||||
u8 readval[2];
|
||||
|
||||
rc = pmi8998_read(chip->regmap, readval, REG_BATT + PARAM_ADDR_BATT_CURRENT, 2);
|
||||
rc = qcom_fg_read(chip->regmap, readval, REG_BATT + PARAM_ADDR_BATT_CURRENT, 2);
|
||||
if (rc) {
|
||||
pr_err("Failed to read current\n");
|
||||
return rc;
|
||||
|
|
@ -163,12 +447,12 @@ static int pmi8998_fg_get_current(struct pmi8998_fg_chip *chip, int *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pmi8998_fg_get_voltage(struct pmi8998_fg_chip *chip, int *val)
|
||||
static int qcom_fg_gen3_get_voltage(struct qcom_fg_chip *chip, int *val)
|
||||
{
|
||||
int rc, temp;
|
||||
u8 readval[2];
|
||||
|
||||
rc = pmi8998_read(chip->regmap, readval, REG_BATT + PARAM_ADDR_BATT_VOLTAGE, 2);
|
||||
rc = qcom_fg_read(chip->regmap, readval, REG_BATT + PARAM_ADDR_BATT_VOLTAGE, 2);
|
||||
if (rc) {
|
||||
pr_err("Failed to read voltage\n");
|
||||
return rc;
|
||||
|
|
@ -183,13 +467,13 @@ static int pmi8998_fg_get_voltage(struct pmi8998_fg_chip *chip, int *val)
|
|||
* Init stuff
|
||||
* ******************/
|
||||
|
||||
static int pmi8998_iacs_clear_sequence(struct pmi8998_fg_chip *chip)
|
||||
static int qcom_fg_iacs_clear_sequence(struct qcom_fg_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 temp;
|
||||
|
||||
/* clear the error */
|
||||
rc = pmi8998_masked_write(chip->regmap, REG_MEM + MEM_INTF_IMA_CFG,
|
||||
rc = qcom_fg_masked_write(chip->regmap, REG_MEM + MEM_INTF_IMA_CFG,
|
||||
BIT(2), BIT(2));
|
||||
if (rc) {
|
||||
pr_err("Error writing to IMA_CFG, rc=%d\n", rc);
|
||||
|
|
@ -197,26 +481,26 @@ static int pmi8998_iacs_clear_sequence(struct pmi8998_fg_chip *chip)
|
|||
}
|
||||
|
||||
temp = 0x4;
|
||||
rc = pmi8998_write(chip->regmap, &temp, REG_MEM + MEM_INTF_ADDR_LSB + 1, 1);
|
||||
rc = qcom_fg_write(chip->regmap, &temp, REG_MEM + MEM_INTF_ADDR_LSB + 1, 1);
|
||||
if (rc) {
|
||||
pr_err("Error writing to MEM_INTF_ADDR_MSB, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
temp = 0x0;
|
||||
rc = pmi8998_write(chip->regmap, &temp, REG_MEM + MEM_INTF_WR_DATA0 + 3, 1);
|
||||
rc = qcom_fg_write(chip->regmap, &temp, REG_MEM + MEM_INTF_WR_DATA0 + 3, 1);
|
||||
if (rc) {
|
||||
pr_err("Error writing to WR_DATA3, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = pmi8998_read(chip->regmap, &temp, REG_MEM + MEM_INTF_RD_DATA0 + 3, 1);
|
||||
rc = qcom_fg_read(chip->regmap, &temp, REG_MEM + MEM_INTF_RD_DATA0 + 3, 1);
|
||||
if (rc) {
|
||||
pr_err("Error writing to RD_DATA3, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = pmi8998_masked_write(chip->regmap, REG_MEM + MEM_INTF_IMA_CFG,
|
||||
rc = qcom_fg_masked_write(chip->regmap, REG_MEM + MEM_INTF_IMA_CFG,
|
||||
BIT(2), 0);
|
||||
if (rc) {
|
||||
pr_err("Error writing to IMA_CFG, rc=%d\n", rc);
|
||||
|
|
@ -225,21 +509,21 @@ static int pmi8998_iacs_clear_sequence(struct pmi8998_fg_chip *chip)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int pmi8998_clear_ima(struct pmi8998_fg_chip *chip,
|
||||
static int qcom_fg_clear_ima(struct qcom_fg_chip *chip,
|
||||
bool check_hw_sts)
|
||||
{
|
||||
int rc = 0, ret = 0;
|
||||
u8 err_sts = 0, exp_sts = 0, hw_sts = 0;
|
||||
bool run_err_clr_seq = false;
|
||||
|
||||
rc = pmi8998_read(chip->regmap, &err_sts,
|
||||
rc = qcom_fg_read(chip->regmap, &err_sts,
|
||||
REG_MEM + MEM_INTF_IMA_ERR_STS, 1);
|
||||
if (rc) {
|
||||
dev_err(chip->dev, "failed to read IMA_ERR_STS, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = pmi8998_read(chip->regmap, &exp_sts,
|
||||
rc = qcom_fg_read(chip->regmap, &exp_sts,
|
||||
REG_MEM + MEM_INTF_IMA_EXP_STS, 1);
|
||||
if (rc) {
|
||||
dev_err(chip->dev, "Error in reading IMA_EXP_STS, rc=%d\n", rc);
|
||||
|
|
@ -247,7 +531,7 @@ static int pmi8998_clear_ima(struct pmi8998_fg_chip *chip,
|
|||
}
|
||||
|
||||
if (check_hw_sts) {
|
||||
rc = pmi8998_read(chip->regmap, &hw_sts,
|
||||
rc = qcom_fg_read(chip->regmap, &hw_sts,
|
||||
REG_MEM + MEM_INTF_IMA_HW_STS, 1);
|
||||
if (rc) {
|
||||
dev_err(chip->dev, "Error in reading IMA_HW_STS, rc=%d\n", rc);
|
||||
|
|
@ -272,7 +556,7 @@ static int pmi8998_clear_ima(struct pmi8998_fg_chip *chip,
|
|||
}
|
||||
|
||||
if (run_err_clr_seq) {
|
||||
ret = pmi8998_iacs_clear_sequence(chip);
|
||||
ret = qcom_fg_iacs_clear_sequence(chip);
|
||||
if (!ret)
|
||||
return -EAGAIN;
|
||||
else
|
||||
|
|
@ -282,7 +566,7 @@ static int pmi8998_clear_ima(struct pmi8998_fg_chip *chip,
|
|||
return rc;
|
||||
}
|
||||
|
||||
int pmi8998_get_prop_usb_online(struct pmi8998_fg_chip *chip, int *val){
|
||||
int qcom_fg_get_prop_usb_online(struct qcom_fg_chip *chip, int *val){
|
||||
unsigned int stat;
|
||||
int rc;
|
||||
|
||||
|
|
@ -297,13 +581,13 @@ int pmi8998_get_prop_usb_online(struct pmi8998_fg_chip *chip, int *val){
|
|||
return rc;
|
||||
}
|
||||
|
||||
int pmi8998_get_prop_batt_status(struct pmi8998_fg_chip *chip, int *val){
|
||||
int qcom_fg_get_prop_batt_status(struct qcom_fg_chip *chip, int *val){
|
||||
int usb_online_val;
|
||||
unsigned int stat;
|
||||
int rc;
|
||||
bool usb_online;
|
||||
|
||||
rc = pmi8998_get_prop_usb_online(chip, &usb_online_val);
|
||||
rc = qcom_fg_get_prop_usb_online(chip, &usb_online_val);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Couldn't get usb online property rc=%d\n", rc);
|
||||
return rc;
|
||||
|
|
@ -346,7 +630,7 @@ int pmi8998_get_prop_batt_status(struct pmi8998_fg_chip *chip, int *val){
|
|||
return rc;
|
||||
}
|
||||
|
||||
int pmi8998_get_prop_health_status(struct pmi8998_fg_chip *chip, int *val){
|
||||
int qcom_fg_get_prop_health_status(struct qcom_fg_chip *chip, int *val){
|
||||
unsigned int stat;
|
||||
int rc;
|
||||
|
||||
|
|
@ -370,7 +654,42 @@ int pmi8998_get_prop_health_status(struct pmi8998_fg_chip *chip, int *val){
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int pmi8998_get_temp_threshold(struct pmi8998_fg_chip *chip,
|
||||
static int qcom_fg_get_temp_threshold(struct qcom_fg_chip *chip,
|
||||
enum power_supply_property psp, int *val)
|
||||
{
|
||||
int rc;
|
||||
u8 temp;
|
||||
int offset;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_TEMP_MIN:
|
||||
offset = 0;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP_MAX:
|
||||
offset = 1;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
|
||||
offset = 2;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
|
||||
offset = 3;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = qcom_fg_sram_read(chip, &temp, 0x454, 1, offset);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Error in reading jeita level for psp:%d, rc=%d\n", psp, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*val = (temp - 30) * 10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_fg_gen3_get_temp_threshold(struct qcom_fg_chip *chip,
|
||||
enum power_supply_property psp, int *val)
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -394,7 +713,7 @@ static int pmi8998_get_temp_threshold(struct pmi8998_fg_chip *chip,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = pmi8998_read(chip->regmap, &temp, reg, 1);
|
||||
rc = qcom_fg_read(chip->regmap, &temp, reg, 1);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Error in reading jeita level for psp:%d, rc=%d\n", psp, rc);
|
||||
return rc;
|
||||
|
|
@ -405,17 +724,66 @@ static int pmi8998_get_temp_threshold(struct pmi8998_fg_chip *chip,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void fg_get_model_name(struct pmi8998_fg_chip *chip, union power_supply_propval *val)
|
||||
static int qcom_fg_set_temp_threshold(struct qcom_fg_chip *chip,
|
||||
enum power_supply_property psp, int val)
|
||||
{
|
||||
int rc;
|
||||
u8 temp;
|
||||
int offset;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_TEMP_MIN:
|
||||
offset = 0;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP_MAX:
|
||||
offset = 1;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
|
||||
offset = 2;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
|
||||
offset = 3;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
temp = val / 10 + 30;
|
||||
|
||||
rc = qcom_fg_sram_write(chip, &temp, 0x454, 1, offset);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Error in writing jeita level for psp:%d, rc=%d\n", psp, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_fg_gen3_set_temp_threshold(struct qcom_fg_chip *chip,
|
||||
enum power_supply_property psp, int val)
|
||||
{
|
||||
/* Not implemented yet */
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
|
||||
static void qcom_fg_get_model_name(struct qcom_fg_chip *chip, union power_supply_propval *val)
|
||||
{
|
||||
switch (chip->subtype)
|
||||
{
|
||||
case PMI8994_SUBTYPE:
|
||||
val->strval = "PMI8994 Battery";
|
||||
break;
|
||||
case PMI8996_SUBTYPE:
|
||||
val->strval = "PMI8996 Battery";
|
||||
break;
|
||||
case PMI8998_SUBTYPE:
|
||||
val->strval = "PMI8998 Battery";
|
||||
break;
|
||||
case PM8998_SUBTYPE:
|
||||
val->strval = "PM8998 Battery";
|
||||
break;
|
||||
//handle pm660 and other socs that use fg3
|
||||
/* Handle other PMICs */
|
||||
default:
|
||||
val->strval = "Unknown PMIC Battery";
|
||||
}
|
||||
|
|
@ -425,7 +793,7 @@ static int fg_get_property(struct power_supply *psy,
|
|||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct pmi8998_fg_chip *chip = power_supply_get_drvdata(psy);
|
||||
struct qcom_fg_chip *chip = power_supply_get_drvdata(psy);
|
||||
int error = 0;
|
||||
|
||||
dev_dbg(chip->dev, "Getting property: %d", psp);
|
||||
|
|
@ -435,19 +803,19 @@ static int fg_get_property(struct power_supply *psy,
|
|||
val->strval = "Qualcomm";
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||
fg_get_model_name(chip, val);
|
||||
qcom_fg_get_model_name(chip, val);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
||||
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
error = pmi8998_fg_get_capacity(chip, &val->intval);
|
||||
error = chip->ops->get_capacity(chip, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||
error = pmi8998_fg_get_current(chip, &val->intval);
|
||||
error = chip->ops->get_current(chip, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
error = pmi8998_fg_get_voltage(chip, &val->intval);
|
||||
error = chip->ops->get_voltage(chip, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
|
||||
|
|
@ -458,23 +826,23 @@ static int fg_get_property(struct power_supply *psy,
|
|||
val->intval = chip->batt_max_voltage_uv;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
error = pmi8998_get_prop_batt_status(chip, &val->intval);
|
||||
error = chip->ops->get_batt_status(chip, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
error = pmi8998_get_prop_health_status(chip, &val->intval);
|
||||
error = chip->ops->get_health_status(chip, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL: /* TODO: Implement capacity learning */
|
||||
val->intval = chip->batt_cap_uah;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
error = pmi8998_fg_get_temperature(chip, &val->intval);
|
||||
error = chip->ops->get_temperature(chip, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP_MIN:
|
||||
case POWER_SUPPLY_PROP_TEMP_MAX:
|
||||
case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
|
||||
case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
|
||||
error = pmi8998_get_temp_threshold(chip, psp, &val->intval);
|
||||
error = chip->ops->get_temp_threshold(chip, psp, &val->intval);
|
||||
break;
|
||||
//POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,POWER_SUPPLY_PROP_TIME_TO_FULL_AVG - calculate time remaining for full charge - implementable
|
||||
//POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG - calculate time remaining when discharging - implementable
|
||||
|
|
@ -500,8 +868,8 @@ static const struct power_supply_desc bms_psy_desc = {
|
|||
.get_property = fg_get_property,
|
||||
};
|
||||
|
||||
irqreturn_t pmi8998_handle_usb_plugin(int irq, void *data){
|
||||
struct pmi8998_fg_chip *chip = data;
|
||||
irqreturn_t qcom_fg_handle_usb_plugin(int irq, void *data){
|
||||
struct qcom_fg_chip *chip = data;
|
||||
int rc;
|
||||
unsigned int stat;
|
||||
bool vbus_rising;
|
||||
|
|
@ -527,10 +895,47 @@ irqreturn_t pmi8998_handle_usb_plugin(int irq, void *data){
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int pmi8998_fg_probe(struct platform_device *pdev)
|
||||
irqreturn_t qcom_fg_handle_mem_avail(int irq, void *data){
|
||||
struct qcom_fg_chip *chip = data;
|
||||
|
||||
if(qcom_fg_sram_check_access(chip)) {
|
||||
complete_all(&chip->sram_access_granted);
|
||||
dev_dbg(chip->dev, "SRAM access granted");
|
||||
} else {
|
||||
dev_dbg(chip->dev, "SRAM access revoked");
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Pre-Gen3 fuel gauge. PMI8996 and older */
|
||||
static const struct qcom_fg_ops ops_fg = {
|
||||
.get_capacity = qcom_fg_get_capacity,
|
||||
.get_temperature = qcom_fg_get_temperature,
|
||||
.get_current = qcom_fg_get_current,
|
||||
.get_voltage = qcom_fg_get_voltage,
|
||||
.get_batt_status = qcom_fg_get_prop_batt_status,
|
||||
.get_health_status = qcom_fg_get_prop_health_status,
|
||||
.get_temp_threshold = qcom_fg_get_temp_threshold,
|
||||
.set_temp_threshold = qcom_fg_set_temp_threshold,
|
||||
};
|
||||
|
||||
/* Gen3 fuel gauge. PMI8998 and newer */
|
||||
static const struct qcom_fg_ops ops_fg_gen3 = {
|
||||
.get_capacity = qcom_fg_get_capacity,
|
||||
.get_temperature = qcom_fg_gen3_get_temperature,
|
||||
.get_current = qcom_fg_gen3_get_current,
|
||||
.get_voltage = qcom_fg_gen3_get_voltage,
|
||||
.get_batt_status = qcom_fg_get_prop_batt_status,
|
||||
.get_health_status = qcom_fg_get_prop_health_status,
|
||||
.get_temp_threshold = qcom_fg_gen3_get_temp_threshold,
|
||||
.set_temp_threshold = qcom_fg_gen3_set_temp_threshold,
|
||||
};
|
||||
|
||||
static int qcom_fg_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct power_supply_config supply_config = {};
|
||||
struct pmi8998_fg_chip *chip;
|
||||
struct qcom_fg_chip *chip;
|
||||
const __be32 *prop_addr;
|
||||
int rc = 0, irq;
|
||||
u8 dma_status;
|
||||
|
|
@ -542,6 +947,8 @@ static int pmi8998_fg_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
chip->dev = &pdev->dev;
|
||||
chip->ops = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
mutex_init(&chip->lock);
|
||||
|
||||
chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
|
|
@ -587,7 +994,7 @@ static int pmi8998_fg_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
// Init memif fn inlined here (chip hardware info)
|
||||
rc = pmi8998_read(chip->regmap, chip->revision, REG_MEM + DIG_MINOR, 4);
|
||||
rc = qcom_fg_read(chip->regmap, chip->revision, REG_MEM + DIG_MINOR, 4);
|
||||
if (rc) {
|
||||
dev_err(chip->dev, "Unable to read FG revision rc=%d\n", rc);
|
||||
return rc;
|
||||
|
|
@ -599,7 +1006,7 @@ static int pmi8998_fg_probe(struct platform_device *pdev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev, "pmi8998 revision DIG:%d.%d ANA:%d.%d\n",
|
||||
dev_dbg(chip->dev, "PMIC revision DIG:%d.%d ANA:%d.%d\n",
|
||||
chip->revision[DIG_MAJOR], chip->revision[DIG_MINOR],
|
||||
chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR]);
|
||||
|
||||
|
|
@ -609,7 +1016,7 @@ static int pmi8998_fg_probe(struct platform_device *pdev)
|
|||
* that the next transaction starts only after the hw is ready.
|
||||
* IACS_INTR_SRC_SLCT is BIT(3)
|
||||
*/
|
||||
rc = pmi8998_masked_write(chip->regmap,
|
||||
rc = qcom_fg_masked_write(chip->regmap,
|
||||
REG_MEM + MEM_INTF_IMA_CFG, BIT(3), BIT(3));
|
||||
if (rc) {
|
||||
dev_err(chip->dev,
|
||||
|
|
@ -618,21 +1025,21 @@ static int pmi8998_fg_probe(struct platform_device *pdev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = pmi8998_clear_ima(chip, true);
|
||||
rc = qcom_fg_clear_ima(chip, true);
|
||||
if (rc && rc != -EAGAIN) {
|
||||
dev_err(chip->dev, "Error clearing IMA, exception rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Check and clear DMA errors
|
||||
rc = pmi8998_read(chip->regmap, &dma_status, REG_MEM + 0x70, 1);
|
||||
rc = qcom_fg_read(chip->regmap, &dma_status, REG_MEM + 0x70, 1);
|
||||
if (rc < 0) {
|
||||
pr_err("failed to read dma_status, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
error_present = dma_status & (BIT(1) | BIT(2));
|
||||
rc = pmi8998_masked_write(chip->regmap, REG_MEM + 0x71, BIT(0),
|
||||
rc = qcom_fg_masked_write(chip->regmap, REG_MEM + 0x71, BIT(0),
|
||||
error_present ? BIT(0) : 0);
|
||||
if (rc < 0) {
|
||||
pr_err("failed to write dma_ctl, rc=%d\n", rc);
|
||||
|
|
@ -651,39 +1058,90 @@ static int pmi8998_fg_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, chip);
|
||||
|
||||
irq = of_irq_get_byname(pdev->dev.of_node, "usb-plugin");
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't get irq usb-plugin byname\n");
|
||||
return irq;
|
||||
/* Initialize IRQs */
|
||||
switch(chip->subtype)
|
||||
{
|
||||
case PMI8994_SUBTYPE:
|
||||
case PMI8996_SUBTYPE:
|
||||
irq = of_irq_get_byname(pdev->dev.of_node, "mem-avail");
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't get irq mem-avail byname\n");
|
||||
return irq;
|
||||
}
|
||||
|
||||
rc = devm_request_threaded_irq(chip->dev, irq, NULL,
|
||||
qcom_fg_handle_mem_avail,
|
||||
IRQF_ONESHOT, "mem-avail", chip);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't request irq %d\n", irq);
|
||||
return rc;
|
||||
}
|
||||
|
||||
init_completion(&chip->sram_access_granted);
|
||||
break;
|
||||
|
||||
case PM8998_SUBTYPE:
|
||||
case PMI8998_SUBTYPE:
|
||||
irq = of_irq_get_byname(pdev->dev.of_node, "usb-plugin");
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't get irq usb-plugin byname\n");
|
||||
return irq;
|
||||
}
|
||||
|
||||
rc = devm_request_threaded_irq(chip->dev, irq, NULL,
|
||||
qcom_fg_handle_usb_plugin,
|
||||
IRQF_ONESHOT, "usb-plugin", chip);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't request irq %d\n", irq);
|
||||
return rc;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
rc = devm_request_threaded_irq(chip->dev, irq, NULL,
|
||||
pmi8998_handle_usb_plugin,
|
||||
IRQF_ONESHOT, "usb-plugin", chip);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't request irq %d\n", irq);
|
||||
// Set default temperature thresholds
|
||||
rc = chip->ops->set_temp_threshold(chip,
|
||||
POWER_SUPPLY_PROP_TEMP_MIN,
|
||||
BATT_TEMP_JEITA_COLD);
|
||||
rc = chip->ops->set_temp_threshold(chip,
|
||||
POWER_SUPPLY_PROP_TEMP_MAX,
|
||||
BATT_TEMP_JEITA_WARM);
|
||||
rc = chip->ops->set_temp_threshold(chip,
|
||||
POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
|
||||
BATT_TEMP_JEITA_COOL);
|
||||
rc = chip->ops->set_temp_threshold(chip,
|
||||
POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
|
||||
BATT_TEMP_JEITA_HOT);
|
||||
if(rc == -ENOTSUPP) {
|
||||
dev_warn(chip->dev,
|
||||
"Setting temperature thresholds not supported");
|
||||
}
|
||||
else if(rc < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Setting temperature thresholds failed: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmi8998_fg_remove(struct platform_device *pdev)
|
||||
static int qcom_fg_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id fg_match_id_table[] = {
|
||||
{ .compatible = "qcom,pmi8998-fg" },
|
||||
{ .compatible = "qcom,pmi8994-fg", .data = &ops_fg },
|
||||
{ .compatible = "qcom,pmi8998-fg", .data = &ops_fg_gen3 },
|
||||
{ /* sentinal */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fg_match_id_table);
|
||||
|
||||
static struct platform_driver qcom_fg_driver = {
|
||||
.probe = pmi8998_fg_probe,
|
||||
.remove = pmi8998_fg_remove,
|
||||
.probe = qcom_fg_probe,
|
||||
.remove = qcom_fg_remove,
|
||||
.driver = {
|
||||
.name = "pmi8998-fg",
|
||||
.name = "qcom-fg",
|
||||
.of_match_table = fg_match_id_table,
|
||||
},
|
||||
};
|
||||
|
|
@ -692,5 +1150,6 @@ module_platform_driver(qcom_fg_driver);
|
|||
|
||||
MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
|
||||
MODULE_AUTHOR("Joel Selvaraj <jo@jsfamily.in>");
|
||||
MODULE_DESCRIPTION("Qualcomm PMI8998 Fuel Guage Driver");
|
||||
MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
|
||||
MODULE_DESCRIPTION("Qualcomm PMIC Fuel Gauge Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -3,19 +3,18 @@
|
|||
|
||||
/**** Registers *****/
|
||||
|
||||
// pmi8998 v2 specific
|
||||
#define BATT_INFO_CHARGE_MAX_DESIGN 0x4a
|
||||
#define PMIC_SUBTYPE 0x105
|
||||
|
||||
#define PMI8994_SUBTYPE 0x0a
|
||||
#define PMI8996_SUBTYPE 0x13
|
||||
#define PM8998_SUBTYPE 0x14
|
||||
#define PMI8998_SUBTYPE 0x15
|
||||
|
||||
|
||||
/* SRAM */
|
||||
#define MEM_INTF_STS 0x10
|
||||
#define MEM_INTF_CFG 0x50
|
||||
#define MEM_INTF_ADDR_LSB 0x61
|
||||
#define MEM_INTF_RD_DATA0 0x67
|
||||
#define MEM_INTF_WR_DATA0 0x63
|
||||
|
||||
#define PMIC_SUBTYPE 0x105
|
||||
|
||||
#define PM8998_SUBTYPE 0x14
|
||||
#define PMI8998_SUBTYPE 0x15
|
||||
|
||||
// pm8950 / pm89988 common
|
||||
#define MEM_INTF_CTL 0x51
|
||||
#define MEM_INTF_IMA_CFG 0x52
|
||||
#define MEM_INTF_IMA_OPR_STS 0x54
|
||||
#define MEM_INTF_IMA_EXP_STS 0x55
|
||||
|
|
@ -23,7 +22,18 @@
|
|||
#define MEM_INTF_BEAT_COUNT 0x57
|
||||
#define MEM_INTF_IMA_ERR_STS 0x5f
|
||||
#define MEM_INTF_IMA_BYTE_EN 0x60
|
||||
#define MEM_INTF_ADDR_LSB 0x61
|
||||
#define MEM_INTF_RD_DATA0 0x67
|
||||
#define MEM_INTF_WR_DATA0 0x63
|
||||
|
||||
#define MEM_INTF_AVAIL BIT(0)
|
||||
#define MEM_INTF_CTL_BURST BIT(7)
|
||||
#define MEM_INTF_CTL_WR_EN BIT(6)
|
||||
#define RIF_MEM_ACCESS_REQ BIT(7)
|
||||
|
||||
|
||||
/* Battery info */
|
||||
#define BATT_INFO_CHARGE_MAX_DESIGN 0x4a
|
||||
#define BATT_INFO_THERM_C1 0x5c
|
||||
#define BATT_INFO_VBATT_LSB 0xa0
|
||||
#define BATT_INFO_VBATT_MSB 0xa1
|
||||
|
|
@ -36,45 +46,58 @@
|
|||
#define BATT_TEMP_LSB_MASK GENMASK(7, 0)
|
||||
#define BATT_TEMP_MSB_MASK GENMASK(2, 0)
|
||||
|
||||
#define REG_BASE 0x4000
|
||||
#define REG_BATT 0x4100
|
||||
#define REG_MEM 0x4400
|
||||
|
||||
/* Base addresses */
|
||||
#define REG_BASE 0x4000
|
||||
#define REG_BATT 0x4100
|
||||
#define REG_MEM 0x4400
|
||||
|
||||
|
||||
/* Interrupt offsets */
|
||||
#define INT_RT_STS 0x10
|
||||
#define INT_EN_CLR 0x16
|
||||
|
||||
// Param addresses
|
||||
#define PARAM_ADDR_BATT_TEMP 0x50
|
||||
#define PARAM_ADDR_BATT_VOLTAGE 0xa0
|
||||
#define PARAM_ADDR_BATT_CURRENT 0xa2
|
||||
|
||||
/* Param addresses */
|
||||
#define PARAM_ADDR_BATT_TEMP 0x50
|
||||
#define PARAM_ADDR_BATT_VOLTAGE 0xa0
|
||||
#define PARAM_ADDR_BATT_CURRENT 0xa2
|
||||
|
||||
|
||||
#define MISC_BASE 0x1600
|
||||
#define USBIN_BASE 0x1300
|
||||
|
||||
|
||||
#define BATT_INFO_JEITA_COLD(chip) (REG_BATT + 0x62)
|
||||
#define BATT_INFO_JEITA_COOL(chip) (REG_BATT + 0x63)
|
||||
#define BATT_INFO_JEITA_WARM(chip) (REG_BATT + 0x64)
|
||||
#define BATT_INFO_JEITA_HOT(chip) (REG_BATT + 0x65)
|
||||
|
||||
#define MISC_BASE 0x1600
|
||||
#define USBIN_BASE 0x1300
|
||||
#define BATT_TEMP_JEITA_COLD 100
|
||||
#define BATT_TEMP_JEITA_COOL 50
|
||||
#define BATT_TEMP_JEITA_WARM 400
|
||||
#define BATT_TEMP_JEITA_HOT 450
|
||||
|
||||
#define BATTERY_CHARGER_STATUS_REG(chip) (chip->chg_base + 0x06)
|
||||
#define BATTERY_HEALTH_STATUS_REG(chip) (chip->chg_base + 0x07)
|
||||
#define BATTERY_HEALTH_STATUS_REG(chip) (chip->chg_base + 0x07)
|
||||
|
||||
#define BATTERY_CHARGER_STATUS_MASK GENMASK(2, 0)
|
||||
#define POWER_PATH_STATUS_REG (MISC_BASE + 0x0B)
|
||||
|
||||
#define MEM_IF_TIMEOUT_MS 5000
|
||||
|
||||
enum wa_flags {
|
||||
PMI8998_V1_REV_WA,
|
||||
PMI8998_V2_REV_WA,
|
||||
};
|
||||
|
||||
enum pmi8998_rev_offsets {
|
||||
enum pmic_rev_offsets {
|
||||
DIG_MINOR = 0x0,
|
||||
DIG_MAJOR = 0x1,
|
||||
ANA_MINOR = 0x2,
|
||||
ANA_MAJOR = 0x3,
|
||||
};
|
||||
enum pmi8998_rev {
|
||||
enum pmic_rev {
|
||||
DIG_REV_1 = 0x1,
|
||||
DIG_REV_2 = 0x2,
|
||||
DIG_REV_3 = 0x3,
|
||||
|
|
@ -112,18 +135,35 @@ static enum power_supply_property fg_properties[] = {
|
|||
POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
|
||||
};
|
||||
|
||||
struct pmi8998_fg_chip {
|
||||
struct qcom_fg_chip;
|
||||
|
||||
struct qcom_fg_ops {
|
||||
int (*get_capacity)(struct qcom_fg_chip *chip, int *);
|
||||
int (*get_temperature)(struct qcom_fg_chip *chip, int *);
|
||||
int (*get_current)(struct qcom_fg_chip *chip, int *);
|
||||
int (*get_voltage)(struct qcom_fg_chip *chip, int *);
|
||||
int (*get_batt_status)(struct qcom_fg_chip *chip, int *);
|
||||
int (*get_health_status)(struct qcom_fg_chip *chip, int *);
|
||||
int (*get_temp_threshold)(struct qcom_fg_chip *chip,
|
||||
enum power_supply_property psp, int *);
|
||||
int (*set_temp_threshold)(struct qcom_fg_chip *chip,
|
||||
enum power_supply_property psp, int);
|
||||
};
|
||||
|
||||
struct qcom_fg_chip {
|
||||
struct device *dev;
|
||||
unsigned int base;
|
||||
unsigned int chg_base;
|
||||
struct regmap *regmap;
|
||||
struct mutex lock;
|
||||
unsigned int subtype;
|
||||
const struct qcom_fg_ops *ops;
|
||||
|
||||
struct power_supply *bms_psy;
|
||||
|
||||
u8 revision[4];
|
||||
bool ima_supported;
|
||||
struct completion sram_access_granted;
|
||||
|
||||
int batt_cap_uah;
|
||||
int batt_max_voltage_uv;
|
||||
Loading…
Add table
Add a link
Reference in a new issue