summaryrefslogtreecommitdiff
path: root/drivers/power/qpnp-fg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/qpnp-fg.c')
-rw-r--r--drivers/power/qpnp-fg.c224
1 files changed, 107 insertions, 117 deletions
diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c
index a9cffbc59eaf..f5e358c0b11c 100644
--- a/drivers/power/qpnp-fg.c
+++ b/drivers/power/qpnp-fg.c
@@ -15,6 +15,7 @@
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/rtc.h>
#include <linux/err.h>
@@ -23,6 +24,7 @@
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
@@ -396,7 +398,8 @@ static void fg_relax(struct fg_wakeup_source *source)
#define THERMAL_COEFF_N_BYTES 6
struct fg_chip {
struct device *dev;
- struct spmi_device *spmi;
+ struct platform_device *pdev;
+ struct regmap *regmap;
u8 pmic_subtype;
u8 pmic_revision[4];
u8 revision[4];
@@ -591,19 +594,19 @@ static void fill_string(char *str, size_t str_len, u8 *buf, int buf_len)
static int fg_write(struct fg_chip *chip, u8 *val, u16 addr, int len)
{
int rc = 0;
- struct spmi_device *spmi = chip->spmi;
+ struct platform_device *pdev = chip->pdev;
char str[DEBUG_PRINT_BUFFER_SIZE];
if ((addr & 0xff00) == 0) {
pr_err("addr cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, len);
+ rc = regmap_bulk_write(chip->regmap, addr, val, len);
if (rc) {
pr_err("write failed addr=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
@@ -611,7 +614,8 @@ static int fg_write(struct fg_chip *chip, u8 *val, u16 addr, int len)
str[0] = '\0';
fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, len);
pr_info("write(0x%04X), sid=%d, len=%d; %s\n",
- addr, spmi->sid, len, str);
+ addr, to_spmi_device(pdev->dev.parent)->usid, len,
+ str);
}
return rc;
@@ -620,19 +624,19 @@ static int fg_write(struct fg_chip *chip, u8 *val, u16 addr, int len)
static int fg_read(struct fg_chip *chip, u8 *val, u16 addr, int len)
{
int rc = 0;
- struct spmi_device *spmi = chip->spmi;
+ struct platform_device *pdev = chip->pdev;
char str[DEBUG_PRINT_BUFFER_SIZE];
if ((addr & 0xff00) == 0) {
pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, len);
+ rc = regmap_bulk_read(chip->regmap, addr, val, len);
if (rc) {
pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", addr,
- spmi->sid, rc);
+ to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
@@ -640,7 +644,8 @@ static int fg_read(struct fg_chip *chip, u8 *val, u16 addr, int len)
str[0] = '\0';
fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, len);
pr_info("read(0x%04x), sid=%d, len=%d; %s\n",
- addr, spmi->sid, len, str);
+ addr, to_spmi_device(pdev->dev.parent)->usid, len,
+ str);
}
return rc;
@@ -650,21 +655,8 @@ static int fg_masked_write(struct fg_chip *chip, u16 addr,
u8 mask, u8 val, int len)
{
int rc;
- u8 reg;
-
- rc = fg_read(chip, &reg, addr, len);
- if (rc) {
- pr_err("spmi read failed: addr=%03X, rc=%d\n", addr, rc);
- return rc;
- }
- pr_debug("addr = 0x%x read 0x%x\n", addr, reg);
-
- reg &= ~mask;
- reg |= val & mask;
-
- pr_debug("Writing 0x%x\n", reg);
- rc = fg_write(chip, &reg, addr, len);
+ rc = regmap_update_bits(chip->regmap, addr, mask, val);
if (rc) {
pr_err("spmi write failed: addr=%03X, rc=%d\n", addr, rc);
return rc;
@@ -4563,7 +4555,7 @@ static int fg_batt_profile_init(struct fg_chip *chip)
{
int rc = 0, ret;
int len;
- struct device_node *node = chip->spmi->dev.of_node;
+ struct device_node *node = chip->pdev->dev.of_node;
struct device_node *batt_node, *profile_node;
const char *data, *batt_type_str;
bool tried_again = false, vbat_in_range, profiles_same;
@@ -4642,7 +4634,7 @@ wait:
* Only configure from profile if fg-cc-cv-threshold-mv is not
* defined in the charger device node.
*/
- if (!of_find_property(chip->spmi->dev.of_node,
+ if (!of_find_property(chip->pdev->dev.of_node,
"qcom,fg-cc-cv-threshold-mv", NULL)) {
of_property_read_u32(profile_node,
"qcom,fg-cc-cv-threshold-mv",
@@ -4757,7 +4749,7 @@ wait:
* Only configure from profile if thermal-coefficients is not
* defined in the FG device node.
*/
- if (!of_find_property(chip->spmi->dev.of_node,
+ if (!of_find_property(chip->pdev->dev.of_node,
"qcom,thermal-coefficients", NULL)) {
data = of_get_property(profile_node,
"qcom,thermal-coefficients", &len);
@@ -5048,7 +5040,7 @@ do { \
if (retval) \
break; \
\
- retval = of_property_read_u32(chip->spmi->dev.of_node, \
+ retval = of_property_read_u32(chip->pdev->dev.of_node, \
"qcom," qpnp_dt_property, \
&settings[type].value); \
\
@@ -5064,7 +5056,7 @@ do { \
if (retval) \
break; \
\
- retval = of_property_read_u32(chip->spmi->dev.of_node, \
+ retval = of_property_read_u32(chip->pdev->dev.of_node, \
"qcom," qpnp_dt_property, \
&store); \
\
@@ -5082,7 +5074,7 @@ static int fg_of_init(struct fg_chip *chip)
{
int rc = 0, sense_type, len = 0;
const char *data;
- struct device_node *node = chip->spmi->dev.of_node;
+ struct device_node *node = chip->pdev->dev.of_node;
u32 temp[2] = {0};
OF_READ_SETTING(FG_MEM_SOFT_HOT, "warm-bat-decidegc", rc, 1);
@@ -5126,7 +5118,7 @@ static int fg_of_init(struct fg_chip *chip)
OF_READ_SETTING(FG_MEM_TERM_CURRENT, "fg-iterm-ma", rc, 1);
OF_READ_SETTING(FG_MEM_CHG_TERM_CURRENT, "fg-chg-iterm-ma", rc, 1);
OF_READ_SETTING(FG_MEM_CUTOFF_VOLTAGE, "fg-cutoff-voltage-mv", rc, 1);
- data = of_get_property(chip->spmi->dev.of_node,
+ data = of_get_property(chip->pdev->dev.of_node,
"qcom,thermal-coefficients", &len);
if (data && len == THERMAL_COEFF_N_BYTES) {
memcpy(chip->thermal_coefficients, data, len);
@@ -5159,31 +5151,30 @@ static int fg_of_init(struct fg_chip *chip)
DEFAULT_EVALUATION_CURRENT_MA);
OF_READ_PROPERTY(chip->cc_cv_threshold_mv,
"fg-cc-cv-threshold-mv", rc, 0);
- if (of_property_read_bool(chip->spmi->dev.of_node,
+ if (of_property_read_bool(chip->pdev->dev.of_node,
"qcom,capacity-learning-on"))
chip->batt_aging_mode = FG_AGING_CC;
- else if (of_property_read_bool(chip->spmi->dev.of_node,
+ else if (of_property_read_bool(chip->pdev->dev.of_node,
"qcom,capacity-estimation-on"))
chip->batt_aging_mode = FG_AGING_ESR;
else
chip->batt_aging_mode = FG_AGING_NONE;
if (chip->batt_aging_mode == FG_AGING_CC) {
- chip->learning_data.feedback_on = of_property_read_bool(
- chip->spmi->dev.of_node,
+ chip->learning_data.feedback_on
+ = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,capacity-learning-feedback");
}
if (fg_debug_mask & FG_AGING)
pr_info("battery aging mode: %d\n", chip->batt_aging_mode);
/* Get the use-otp-profile property */
- chip->use_otp_profile = of_property_read_bool(
- chip->spmi->dev.of_node,
+ chip->use_otp_profile = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,use-otp-profile");
- chip->hold_soc_while_full = of_property_read_bool(
- chip->spmi->dev.of_node,
+ chip->hold_soc_while_full
+ = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,hold-soc-while-full");
- sense_type = of_property_read_bool(chip->spmi->dev.of_node,
+ sense_type = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,ext-sense-type");
if (rc == 0) {
if (fg_sense_type < 0)
@@ -5218,32 +5209,32 @@ static int fg_of_init(struct fg_chip *chip)
static int fg_init_irqs(struct fg_chip *chip)
{
int rc = 0;
- struct resource *resource;
- struct spmi_resource *spmi_resource;
+ unsigned int base;
+ struct device_node *child;
u8 subtype;
- struct spmi_device *spmi = chip->spmi;
+ struct platform_device *pdev = chip->pdev;
- spmi_for_each_container_dev(spmi_resource, spmi) {
- if (!spmi_resource) {
- pr_err("fg: spmi resource absent\n");
- return rc;
- }
+ if (of_get_available_child_count(pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ return -ENXIO;
+ }
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- pr_err("node %s IO resource absent!\n",
- spmi->dev.of_node->full_name);
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ child->full_name, rc);
return rc;
}
- if ((resource->start == chip->vbat_adc_addr) ||
- (resource->start == chip->ibat_adc_addr) ||
- (resource->start == chip->tp_rev_addr))
+ if ((base == chip->vbat_adc_addr) ||
+ (base == chip->ibat_adc_addr) ||
+ (base == chip->tp_rev_addr))
continue;
rc = fg_read(chip, &subtype,
- resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+ base + REG_OFFSET_PERP_SUBTYPE, 1);
if (rc) {
pr_err("Peripheral subtype read failed rc=%d\n", rc);
return rc;
@@ -5251,26 +5242,26 @@ static int fg_init_irqs(struct fg_chip *chip)
switch (subtype) {
case FG_SOC:
- chip->soc_irq[FULL_SOC].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "full-soc");
+ chip->soc_irq[FULL_SOC].irq = of_irq_get_byname(child,
+ "full-soc");
if (chip->soc_irq[FULL_SOC].irq < 0) {
pr_err("Unable to get full-soc irq\n");
return rc;
}
- chip->soc_irq[EMPTY_SOC].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "empty-soc");
+ chip->soc_irq[EMPTY_SOC].irq = of_irq_get_byname(child,
+ "empty-soc");
if (chip->soc_irq[EMPTY_SOC].irq < 0) {
pr_err("Unable to get low-soc irq\n");
return rc;
}
- chip->soc_irq[DELTA_SOC].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "delta-soc");
+ chip->soc_irq[DELTA_SOC].irq = of_irq_get_byname(child,
+ "delta-soc");
if (chip->soc_irq[DELTA_SOC].irq < 0) {
pr_err("Unable to get delta-soc irq\n");
return rc;
}
- chip->soc_irq[FIRST_EST_DONE].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "first-est-done");
+ chip->soc_irq[FIRST_EST_DONE].irq
+ = of_irq_get_byname(child, "first-est-done");
if (chip->soc_irq[FIRST_EST_DONE].irq < 0) {
pr_err("Unable to get first-est-done irq\n");
return rc;
@@ -5319,8 +5310,8 @@ static int fg_init_irqs(struct fg_chip *chip)
enable_irq_wake(chip->soc_irq[EMPTY_SOC].irq);
break;
case FG_MEMIF:
- chip->mem_irq[FG_MEM_AVAIL].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "mem-avail");
+ chip->mem_irq[FG_MEM_AVAIL].irq
+ = of_irq_get_byname(child, "mem-avail");
if (chip->mem_irq[FG_MEM_AVAIL].irq < 0) {
pr_err("Unable to get mem-avail irq\n");
return rc;
@@ -5338,9 +5329,8 @@ static int fg_init_irqs(struct fg_chip *chip)
}
break;
case FG_BATT:
- chip->batt_irq[BATT_MISSING].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource,
- "batt-missing");
+ chip->batt_irq[BATT_MISSING].irq
+ = of_irq_get_byname(child, "batt-missing");
if (chip->batt_irq[BATT_MISSING].irq < 0) {
pr_err("Unable to get batt-missing irq\n");
rc = -EINVAL;
@@ -5359,9 +5349,8 @@ static int fg_init_irqs(struct fg_chip *chip)
chip->batt_irq[BATT_MISSING].irq, rc);
return rc;
}
- chip->batt_irq[VBATT_LOW].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource,
- "vbatt-low");
+ chip->batt_irq[VBATT_LOW].irq
+ = of_irq_get_byname(child, "vbatt-low");
if (chip->batt_irq[VBATT_LOW].irq < 0) {
pr_err("Unable to get vbatt-low irq\n");
rc = -EINVAL;
@@ -5427,12 +5416,12 @@ static void fg_cleanup(struct fg_chip *chip)
wakeup_source_trash(&chip->capacity_learning_wakeup_source.source);
}
-static int fg_remove(struct spmi_device *spmi)
+static int fg_remove(struct platform_device *pdev)
{
- struct fg_chip *chip = dev_get_drvdata(&spmi->dev);
+ struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
fg_cleanup(chip);
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
@@ -6176,7 +6165,7 @@ static int fg_detect_pmic_type(struct fg_chip *chip)
struct pmic_revid_data *pmic_rev_id;
struct device_node *revid_dev_node;
- revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
+ revid_dev_node = of_parse_phandle(chip->pdev->dev.of_node,
"qcom,pmic-revid", 0);
if (!revid_dev_node) {
pr_err("Missing qcom,pmic-revid property - driver failed\n");
@@ -6309,21 +6298,21 @@ done:
fg_cleanup(chip);
}
-static int fg_probe(struct spmi_device *spmi)
+static int fg_probe(struct platform_device *pdev)
{
- struct device *dev = &(spmi->dev);
+ struct device *dev = &(pdev->dev);
struct fg_chip *chip;
- struct spmi_resource *spmi_resource;
- struct resource *resource;
+ struct device_node *child;
+ unsigned int base;
u8 subtype, reg;
int rc = 0;
- if (!spmi) {
+ if (!pdev) {
pr_err("no valid spmi pointer\n");
return -ENODEV;
}
- if (!spmi->dev.of_node) {
+ if (!pdev->dev.of_node) {
pr_err("device node missing\n");
return -ENODEV;
}
@@ -6333,9 +6322,14 @@ static int fg_probe(struct spmi_device *spmi)
pr_err("Can't allocate fg_chip\n");
return -ENOMEM;
}
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
- chip->spmi = spmi;
- chip->dev = &(spmi->dev);
+ chip->pdev = pdev;
+ chip->dev = &(pdev->dev);
wakeup_source_init(&chip->empty_check_wakeup_source.source,
"qpnp_fg_empty_check");
@@ -6383,40 +6377,36 @@ static int fg_probe(struct spmi_device *spmi)
complete_all(&chip->sram_access_revoked);
init_completion(&chip->batt_id_avail);
init_completion(&chip->first_soc_done);
- dev_set_drvdata(&spmi->dev, chip);
+ dev_set_drvdata(&pdev->dev, chip);
- spmi_for_each_container_dev(spmi_resource, spmi) {
- if (!spmi_resource) {
- pr_err("qpnp_chg: spmi resource absent\n");
- rc = -ENXIO;
- goto of_init_fail;
- }
+ if (of_get_available_child_count(pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ rc = -ENXIO;
+ goto of_init_fail;
+ }
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- pr_err("node %s IO resource absent!\n",
- spmi->dev.of_node->full_name);
- rc = -ENXIO;
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ child->full_name, rc);
goto of_init_fail;
}
- if (strcmp("qcom,fg-adc-vbat",
- spmi_resource->of_node->name) == 0) {
- chip->vbat_adc_addr = resource->start;
+ if (strcmp("qcom,fg-adc-vbat", child->name) == 0) {
+ chip->vbat_adc_addr = base;
continue;
- } else if (strcmp("qcom,fg-adc-ibat",
- spmi_resource->of_node->name) == 0) {
- chip->ibat_adc_addr = resource->start;
+ } else if (strcmp("qcom,fg-adc-ibat", child->name) == 0) {
+ chip->ibat_adc_addr = base;
continue;
- } else if (strcmp("qcom,revid-tp-rev",
- spmi_resource->of_node->name) == 0) {
- chip->tp_rev_addr = resource->start;
+ } else if (strcmp("qcom,revid-tp-rev", child->name) == 0) {
+ chip->tp_rev_addr = base;
continue;
}
rc = fg_read(chip, &subtype,
- resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+ base + REG_OFFSET_PERP_SUBTYPE, 1);
if (rc) {
pr_err("Peripheral subtype read failed rc=%d\n", rc);
goto of_init_fail;
@@ -6424,13 +6414,13 @@ static int fg_probe(struct spmi_device *spmi)
switch (subtype) {
case FG_SOC:
- chip->soc_base = resource->start;
+ chip->soc_base = base;
break;
case FG_MEMIF:
- chip->mem_base = resource->start;
+ chip->mem_base = base;
break;
case FG_BATT:
- chip->batt_base = resource->start;
+ chip->batt_base = base;
break;
default:
pr_err("Invalid peripheral subtype=0x%x\n", subtype);
@@ -6693,11 +6683,11 @@ static struct kernel_param_ops fg_restart_ops = {
module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
-static struct spmi_driver fg_driver = {
+static struct platform_driver fg_driver = {
.driver = {
- .name = QPNP_FG_DEV_NAME,
+ .name = QPNP_FG_DEV_NAME,
.of_match_table = fg_match_table,
- .pm = &qpnp_fg_pm_ops,
+ .pm = &qpnp_fg_pm_ops,
},
.probe = fg_probe,
.remove = fg_remove,
@@ -6705,12 +6695,12 @@ static struct spmi_driver fg_driver = {
static int __init fg_init(void)
{
- return spmi_driver_register(&fg_driver);
+ return platform_driver_register(&fg_driver);
}
static void __exit fg_exit(void)
{
- return spmi_driver_unregister(&fg_driver);
+ return platform_driver_unregister(&fg_driver);
}
module_init(fg_init);