From e5f8763d748a01c700ec0dc55502f40bb62940f1 Mon Sep 17 00:00:00 2001 From: Joel Selvaraj Date: Thu, 31 Dec 2020 16:35:41 +0530 Subject: [PATCH] power: supply: add battery charging status feature --- drivers/power/supply/pmi8998_fg.c | 106 +++++++++++++++++++++++++++--- drivers/power/supply/pmi8998_fg.h | 7 ++ 2 files changed, 105 insertions(+), 8 deletions(-) diff --git a/drivers/power/supply/pmi8998_fg.c b/drivers/power/supply/pmi8998_fg.c index ba2cf70ecc15..f38f1984b59c 100644 --- a/drivers/power/supply/pmi8998_fg.c +++ b/drivers/power/supply/pmi8998_fg.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "pmi8998_fg.h" @@ -318,6 +320,70 @@ 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){ + unsigned int stat; + int rc; + + rc = regmap_read(chip->regmap, POWER_PATH_STATUS_REG, &stat); + if (rc < 0){ + dev_err(chip->dev, "Couldn't read POWER_PATH_STATUS! ret=%d\n", rc); + return rc; + } + + dev_dbg(chip->dev, "USB POWER_PATH_STATUS : 0x%02x\n", stat); + *val = (stat & BIT(4)) && (stat & BIT(0)); + return rc; +} + +int pmi8998_get_prop_batt_status(struct pmi8998_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); + if (rc < 0) { + dev_err(chip->dev, "Couldn't get usb online property rc=%d\n", rc); + return rc; + } + dev_dbg(chip->dev, "USB ONLINE val : %d\n", usb_online_val); + usb_online = (bool)usb_online_val; + + if (!usb_online) { + *val = POWER_SUPPLY_STATUS_DISCHARGING; + return rc; + } + + rc = regmap_read(chip->regmap, BATTERY_CHARGER_STATUS_REG(chip), &stat); + if (rc < 0){ + dev_err(chip->dev, "Charging status REGMAP read failed! ret=%d\n", rc); + return rc; + } + + stat = stat & BATTERY_CHARGER_STATUS_MASK; + dev_dbg(chip->dev, "Charging status : %d!\n", stat); + + switch (stat) { + case TRICKLE_CHARGE: + case PRE_CHARGE: + case FAST_CHARGE: + case FULLON_CHARGE: + case TAPER_CHARGE: + case TERMINATE_CHARGE: + case INHIBIT_CHARGE: + *val = POWER_SUPPLY_STATUS_CHARGING; + break; + case DISABLE_CHARGE: + *val = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + default: + *val = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + + return rc; +} + static int fg_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -325,7 +391,7 @@ static int fg_get_property(struct power_supply *psy, struct pmi8998_fg_chip *chip = power_supply_get_drvdata(psy); int error = 0; - dev_info(chip->dev, "Getting property: %d", psp); + dev_dbg(chip->dev, "Getting property: %d", psp); switch (psp) { case POWER_SUPPLY_PROP_MANUFACTURER: @@ -360,8 +426,7 @@ static int fg_get_property(struct power_supply *psy, val->intval = chip->batt_info.nom_cap_uah; break; case POWER_SUPPLY_PROP_STATUS: - val->intval = POWER_SUPPLY_STATUS_CHARGING; - //error = smb2_chg_get_status(chip, &val->intval); + error = pmi8998_get_prop_batt_status(chip, &val->intval); break; case POWER_SUPPLY_PROP_HEALTH: val->intval = POWER_SUPPLY_HEALTH_GOOD; @@ -402,12 +467,19 @@ static int pmi8998_fg_of_battery_init(struct pmi8998_fg_chip *chip){ return rc; } +irqreturn_t pmi8998_handle_usb_plugin(int irq, void *data){ + struct pmi8998_fg_chip *chip = data; + dev_dbg(chip->dev, "USB IRQ called!\n"); + power_supply_changed(chip->bms_psy); + return IRQ_HANDLED; +} + static int pmi8998_fg_probe(struct platform_device *pdev) { struct power_supply_config supply_config = {}; struct pmi8998_fg_chip *chip; const __be32 *prop_addr; - int rc = 0; + int rc = 0, irq; u8 dma_status; bool error_present; @@ -433,6 +505,13 @@ static int pmi8998_fg_probe(struct platform_device *pdev) } chip->base = be32_to_cpu(*prop_addr); + prop_addr = of_get_address(pdev->dev.of_node, 1, NULL, NULL); + if (!prop_addr) { + dev_err(chip->dev, "Couldn't read CHG base address from dt\n"); + return -EINVAL; + } + chip->chg_base = be32_to_cpu(*prop_addr); + // Init memif fn inlined here (chip hardware info) rc = pmi8998_read(chip->regmap, chip->revision, REG_MEM(chip) + DIG_MINOR, 4); if (rc) { @@ -479,10 +558,6 @@ static int pmi8998_fg_probe(struct platform_device *pdev) pr_err("failed to write dma_ctl, rc=%d\n", rc); return rc; } - - dev_dbg(chip->dev, "probed revision DIG:%d.%d ANA:%d.%d\n", - chip->revision[DIG_MAJOR], chip->revision[DIG_MINOR], - chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR]); supply_config.drv_data = chip; supply_config.of_node = pdev->dev.of_node; @@ -495,6 +570,21 @@ 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; + } + + 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); + return rc; + } + return 0; } diff --git a/drivers/power/supply/pmi8998_fg.h b/drivers/power/supply/pmi8998_fg.h index 20dd2d2fc6e8..81a90945c0e6 100644 --- a/drivers/power/supply/pmi8998_fg.h +++ b/drivers/power/supply/pmi8998_fg.h @@ -46,6 +46,12 @@ #define PARAM_ADDR_BATT_VOLTAGE 0xa0 #define PARAM_ADDR_BATT_CURRENT 0xa2 +#define MISC_BASE 0x1600 + +#define BATTERY_CHARGER_STATUS_REG(chip) (chip->chg_base + 0x06) +#define BATTERY_CHARGER_STATUS_MASK GENMASK(2, 0) +#define POWER_PATH_STATUS_REG (MISC_BASE + 0x0B) + enum wa_flags { PMI8998_V1_REV_WA, PMI8998_V2_REV_WA, @@ -121,6 +127,7 @@ struct battery_info { struct pmi8998_fg_chip { struct device *dev; unsigned int base; + unsigned int chg_base; struct regmap *regmap; struct mutex lock;