All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe()
@ 2022-01-06 11:06 Hans de Goede
  2022-01-06 11:06 ` [PATCH 2/7] power: supply: axp288_fuel_gauge: Add axp288_fuel_gauge_read_initial_regs() Hans de Goede
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Hans de Goede @ 2022-01-06 11:06 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, linux-pm

Add a dev local variable to probe() as shortcut for &pdev->dev, this is
a preparation change for making more use of devm managed resources.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index c1da217fdb0e..1495402f440c 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -622,16 +622,17 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 		[BAT_D_CURR] = "axp288-chrg-d-curr",
 		[BAT_VOLT] = "axp288-batt-volt",
 	};
+	struct device *dev = &pdev->dev;
 	unsigned int val;
 
 	if (dmi_check_system(axp288_no_battery_list))
 		return -ENODEV;
 
-	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	info->dev = &pdev->dev;
+	info->dev = dev;
 	info->regmap = axp20x->regmap;
 	info->regmap_irqc = axp20x->regmap_irqc;
 	info->status = POWER_SUPPLY_STATUS_UNKNOWN;
@@ -651,8 +652,7 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 			iio_channel_get(NULL, iio_chan_name[i]);
 		if (IS_ERR(info->iio_channel[i])) {
 			ret = PTR_ERR(info->iio_channel[i]);
-			dev_dbg(&pdev->dev, "error getting iiochan %s: %d\n",
-				iio_chan_name[i], ret);
+			dev_dbg(dev, "error getting iiochan %s: %d\n", iio_chan_name[i], ret);
 			/* Wait for axp288_adc to load */
 			if (ret == -ENODEV)
 				ret = -EPROBE_DEFER;
@@ -722,10 +722,10 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 		goto out_free_iio_chan;
 
 	psy_cfg.drv_data = info;
-	info->bat = power_supply_register(&pdev->dev, &fuel_gauge_desc, &psy_cfg);
+	info->bat = power_supply_register(dev, &fuel_gauge_desc, &psy_cfg);
 	if (IS_ERR(info->bat)) {
 		ret = PTR_ERR(info->bat);
-		dev_err(&pdev->dev, "failed to register battery: %d\n", ret);
+		dev_err(dev, "failed to register battery: %d\n", ret);
 		goto out_free_iio_chan;
 	}
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/7] power: supply: axp288_fuel_gauge: Add axp288_fuel_gauge_read_initial_regs()
  2022-01-06 11:06 [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe() Hans de Goede
@ 2022-01-06 11:06 ` Hans de Goede
  2022-01-06 11:06 ` [PATCH 3/7] power: supply: axp288_fuel_gauge: Use devm_add_action_or_reset() for iio chan release Hans de Goede
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2022-01-06 11:06 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, linux-pm

Refactor probe a bit, introducing a new
axp288_fuel_gauge_read_initial_regs() helper. This replaces a whole
bunch of gotos and removes the unblock_punit_i2c_access label.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 109 ++++++++++++-----------
 1 file changed, 56 insertions(+), 53 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index 1495402f440c..35f9edf3da09 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -611,6 +611,61 @@ static const struct dmi_system_id axp288_no_battery_list[] = {
 	{}
 };
 
+static int axp288_fuel_gauge_read_initial_regs(struct axp288_fg_info *info)
+{
+	unsigned int val;
+	int ret;
+
+	/*
+	 * On some devices the fuelgauge and charger parts of the axp288 are
+	 * not used, check that the fuelgauge is enabled (CC_CTRL != 0).
+	 */
+	ret = regmap_read(info->regmap, AXP20X_CC_CTRL, &val);
+	if (ret < 0)
+		return ret;
+	if (val == 0)
+		return -ENODEV;
+
+	ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG);
+	if (ret < 0)
+		return ret;
+
+	if (!(ret & FG_DES_CAP1_VALID)) {
+		dev_err(info->dev, "axp288 not configured by firmware\n");
+		return -ENODEV;
+	}
+
+	ret = fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1);
+	if (ret < 0)
+		return ret;
+	switch ((ret & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS) {
+	case CHRG_CCCV_CV_4100MV:
+		info->max_volt = 4100;
+		break;
+	case CHRG_CCCV_CV_4150MV:
+		info->max_volt = 4150;
+		break;
+	case CHRG_CCCV_CV_4200MV:
+		info->max_volt = 4200;
+		break;
+	case CHRG_CCCV_CV_4350MV:
+		info->max_volt = 4350;
+		break;
+	}
+
+	ret = fuel_gauge_reg_readb(info, AXP20X_PWR_OP_MODE);
+	if (ret < 0)
+		return ret;
+	info->pwr_op = ret;
+
+	ret = fuel_gauge_reg_readb(info, AXP288_FG_LOW_CAP_REG);
+	if (ret < 0)
+		return ret;
+	info->low_cap = ret;
+
+	return 0;
+}
+
 static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 {
 	int i, ret = 0;
@@ -623,7 +678,6 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 		[BAT_VOLT] = "axp288-batt-volt",
 	};
 	struct device *dev = &pdev->dev;
-	unsigned int val;
 
 	if (dmi_check_system(axp288_no_battery_list))
 		return -ENODEV;
@@ -665,59 +719,8 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto out_free_iio_chan;
 
-	/*
-	 * On some devices the fuelgauge and charger parts of the axp288 are
-	 * not used, check that the fuelgauge is enabled (CC_CTRL != 0).
-	 */
-	ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val);
-	if (ret < 0)
-		goto unblock_punit_i2c_access;
-	if (val == 0) {
-		ret = -ENODEV;
-		goto unblock_punit_i2c_access;
-	}
-
-	ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG);
-	if (ret < 0)
-		goto unblock_punit_i2c_access;
-
-	if (!(ret & FG_DES_CAP1_VALID)) {
-		dev_err(&pdev->dev, "axp288 not configured by firmware\n");
-		ret = -ENODEV;
-		goto unblock_punit_i2c_access;
-	}
-
-	ret = fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1);
-	if (ret < 0)
-		goto unblock_punit_i2c_access;
-	switch ((ret & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS) {
-	case CHRG_CCCV_CV_4100MV:
-		info->max_volt = 4100;
-		break;
-	case CHRG_CCCV_CV_4150MV:
-		info->max_volt = 4150;
-		break;
-	case CHRG_CCCV_CV_4200MV:
-		info->max_volt = 4200;
-		break;
-	case CHRG_CCCV_CV_4350MV:
-		info->max_volt = 4350;
-		break;
-	}
-
-	ret = fuel_gauge_reg_readb(info, AXP20X_PWR_OP_MODE);
-	if (ret < 0)
-		goto unblock_punit_i2c_access;
-	info->pwr_op = ret;
-
-	ret = fuel_gauge_reg_readb(info, AXP288_FG_LOW_CAP_REG);
-	if (ret < 0)
-		goto unblock_punit_i2c_access;
-	info->low_cap = ret;
-
-unblock_punit_i2c_access:
+	ret = axp288_fuel_gauge_read_initial_regs(info);
 	iosf_mbi_unblock_punit_i2c_access();
-	/* In case we arrive here by goto because of a register access error */
 	if (ret < 0)
 		goto out_free_iio_chan;
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/7] power: supply: axp288_fuel_gauge: Use devm_add_action_or_reset() for iio chan release
  2022-01-06 11:06 [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe() Hans de Goede
  2022-01-06 11:06 ` [PATCH 2/7] power: supply: axp288_fuel_gauge: Add axp288_fuel_gauge_read_initial_regs() Hans de Goede
@ 2022-01-06 11:06 ` Hans de Goede
  2022-01-06 11:06 ` [PATCH 4/7] power: supply: axp288_fuel_gauge: Use devm_power_supply_register() Hans de Goede
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2022-01-06 11:06 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, linux-pm

An existing comment already mentions we: "cannot use devm_iio_channel_get
because x86 systems lack the device<->channel maps which iio_channel_get
will try to use when passed a non NULL device pointer".

Work around this by registering a devm action to free the iio-channels.
This is a step on the way to fully converting the probe() function to
only use devm managed resources.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 33 ++++++++++++++----------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index 35f9edf3da09..aaf2d5542316 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -666,6 +666,16 @@ static int axp288_fuel_gauge_read_initial_regs(struct axp288_fg_info *info)
 	return 0;
 }
 
+static void axp288_fuel_gauge_release_iio_chans(void *data)
+{
+	struct axp288_fg_info *info = data;
+	int i;
+
+	for (i = 0; i < IIO_CHANNEL_NUM; i++)
+		if (!IS_ERR_OR_NULL(info->iio_channel[i]))
+			iio_channel_release(info->iio_channel[i]);
+}
+
 static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 {
 	int i, ret = 0;
@@ -711,37 +721,35 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 			if (ret == -ENODEV)
 				ret = -EPROBE_DEFER;
 
-			goto out_free_iio_chan;
+			axp288_fuel_gauge_release_iio_chans(info);
+			return ret;
 		}
 	}
 
+	ret = devm_add_action_or_reset(dev, axp288_fuel_gauge_release_iio_chans, info);
+	if (ret)
+		return ret;
+
 	ret = iosf_mbi_block_punit_i2c_access();
 	if (ret < 0)
-		goto out_free_iio_chan;
+		return ret;
 
 	ret = axp288_fuel_gauge_read_initial_regs(info);
 	iosf_mbi_unblock_punit_i2c_access();
 	if (ret < 0)
-		goto out_free_iio_chan;
+		return ret;
 
 	psy_cfg.drv_data = info;
 	info->bat = power_supply_register(dev, &fuel_gauge_desc, &psy_cfg);
 	if (IS_ERR(info->bat)) {
 		ret = PTR_ERR(info->bat);
 		dev_err(dev, "failed to register battery: %d\n", ret);
-		goto out_free_iio_chan;
+		return ret;
 	}
 
 	fuel_gauge_init_irq(info, pdev);
 
 	return 0;
-
-out_free_iio_chan:
-	for (i = 0; i < IIO_CHANNEL_NUM; i++)
-		if (!IS_ERR_OR_NULL(info->iio_channel[i]))
-			iio_channel_release(info->iio_channel[i]);
-
-	return ret;
 }
 
 static const struct platform_device_id axp288_fg_id_table[] = {
@@ -761,9 +769,6 @@ static int axp288_fuel_gauge_remove(struct platform_device *pdev)
 		if (info->irq[i] >= 0)
 			free_irq(info->irq[i], info);
 
-	for (i = 0; i < IIO_CHANNEL_NUM; i++)
-		iio_channel_release(info->iio_channel[i]);
-
 	return 0;
 }
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/7] power: supply: axp288_fuel_gauge: Use devm_power_supply_register()
  2022-01-06 11:06 [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe() Hans de Goede
  2022-01-06 11:06 ` [PATCH 2/7] power: supply: axp288_fuel_gauge: Add axp288_fuel_gauge_read_initial_regs() Hans de Goede
  2022-01-06 11:06 ` [PATCH 3/7] power: supply: axp288_fuel_gauge: Use devm_add_action_or_reset() for iio chan release Hans de Goede
@ 2022-01-06 11:06 ` Hans de Goede
  2022-01-06 11:06 ` [PATCH 5/7] power: supply: axp288_fuel_gauge: Refactor IRQ initialization Hans de Goede
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2022-01-06 11:06 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, linux-pm

Use devm_power_supply_register() instead of
power_supply_register().

Note as a side-effect this changes the release order so that now
first the IRQs get free-ed and then the psy gets unregistered.
This is actually a bug-fix since this fixes the IRQ possibly trying
to reference the unregistered psy.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index aaf2d5542316..cefde85e3309 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -740,7 +740,7 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 		return ret;
 
 	psy_cfg.drv_data = info;
-	info->bat = power_supply_register(dev, &fuel_gauge_desc, &psy_cfg);
+	info->bat = devm_power_supply_register(dev, &fuel_gauge_desc, &psy_cfg);
 	if (IS_ERR(info->bat)) {
 		ret = PTR_ERR(info->bat);
 		dev_err(dev, "failed to register battery: %d\n", ret);
@@ -763,8 +763,6 @@ static int axp288_fuel_gauge_remove(struct platform_device *pdev)
 	struct axp288_fg_info *info = platform_get_drvdata(pdev);
 	int i;
 
-	power_supply_unregister(info->bat);
-
 	for (i = 0; i < AXP288_FG_INTR_NUM; i++)
 		if (info->irq[i] >= 0)
 			free_irq(info->irq[i], info);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/7] power: supply: axp288_fuel_gauge: Refactor IRQ initialization
  2022-01-06 11:06 [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe() Hans de Goede
                   ` (2 preceding siblings ...)
  2022-01-06 11:06 ` [PATCH 4/7] power: supply: axp288_fuel_gauge: Use devm_power_supply_register() Hans de Goede
@ 2022-01-06 11:06 ` Hans de Goede
  2022-01-06 11:06 ` [PATCH 6/7] power: supply: axp288_fuel_gauge: Take lock before updating the valid flag Hans de Goede
  2022-01-06 11:06 ` [PATCH 7/7] power: supply: axp288_fuel_gauge: Add a no_current_sense_res module_param Hans de Goede
  5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2022-01-06 11:06 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, linux-pm

Refactor the IRQ initialization code:

* Move the looking up of the vIRQs to the beginning of probe(), failing
  probe early if this fails
* Do the actual requesting of IRQs inline in probe() and properly abort
  probe() on errors
* Use devm_request_threaded_irq(), completing the conversion of probe() to
  only use devm managed resources and remove the remove() driver function.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 66 ++++++------------------
 1 file changed, 17 insertions(+), 49 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index cefde85e3309..f7dce029266a 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -107,7 +107,6 @@ enum {
 struct axp288_fg_info {
 	struct device *dev;
 	struct regmap *regmap;
-	struct regmap_irq_chip_data *regmap_irqc;
 	int irq[AXP288_FG_INTR_NUM];
 	struct iio_channel *iio_channel[IIO_CHANNEL_NUM];
 	struct power_supply *bat;
@@ -502,38 +501,6 @@ static const struct power_supply_desc fuel_gauge_desc = {
 	.external_power_changed	= fuel_gauge_external_power_changed,
 };
 
-static void fuel_gauge_init_irq(struct axp288_fg_info *info, struct platform_device *pdev)
-{
-	int ret, i, pirq;
-
-	for (i = 0; i < AXP288_FG_INTR_NUM; i++) {
-		pirq = platform_get_irq(pdev, i);
-		info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
-		if (info->irq[i] < 0) {
-			dev_warn(info->dev, "regmap_irq get virq failed for IRQ %d: %d\n",
-				pirq, info->irq[i]);
-			info->irq[i] = -1;
-			goto intr_failed;
-		}
-		ret = request_threaded_irq(info->irq[i],
-				NULL, fuel_gauge_thread_handler,
-				IRQF_ONESHOT, DEV_NAME, info);
-		if (ret) {
-			dev_warn(info->dev, "request irq failed for IRQ %d: %d\n",
-				pirq, info->irq[i]);
-			info->irq[i] = -1;
-			goto intr_failed;
-		}
-	}
-	return;
-
-intr_failed:
-	for (; i > 0; i--) {
-		free_irq(info->irq[i - 1], info);
-		info->irq[i - 1] = -1;
-	}
-}
-
 /*
  * Some devices have no battery (HDMI sticks) and the axp288 battery's
  * detection reports one despite it not being there.
@@ -678,7 +645,6 @@ static void axp288_fuel_gauge_release_iio_chans(void *data)
 
 static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 {
-	int i, ret = 0;
 	struct axp288_fg_info *info;
 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
 	struct power_supply_config psy_cfg = {};
@@ -688,6 +654,7 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 		[BAT_VOLT] = "axp288-batt-volt",
 	};
 	struct device *dev = &pdev->dev;
+	int i, pirq, ret;
 
 	if (dmi_check_system(axp288_no_battery_list))
 		return -ENODEV;
@@ -698,7 +665,6 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 
 	info->dev = dev;
 	info->regmap = axp20x->regmap;
-	info->regmap_irqc = axp20x->regmap_irqc;
 	info->status = POWER_SUPPLY_STATUS_UNKNOWN;
 	info->valid = 0;
 
@@ -706,6 +672,15 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 
 	mutex_init(&info->lock);
 
+	for (i = 0; i < AXP288_FG_INTR_NUM; i++) {
+		pirq = platform_get_irq(pdev, i);
+		ret = regmap_irq_get_virq(axp20x->regmap_irqc, pirq);
+		if (ret < 0)
+			return dev_err_probe(dev, ret, "getting vIRQ %d\n", pirq);
+
+		info->irq[i] = ret;
+	}
+
 	for (i = 0; i < IIO_CHANNEL_NUM; i++) {
 		/*
 		 * Note cannot use devm_iio_channel_get because x86 systems
@@ -747,7 +722,13 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	fuel_gauge_init_irq(info, pdev);
+	for (i = 0; i < AXP288_FG_INTR_NUM; i++) {
+		ret = devm_request_threaded_irq(dev, info->irq[i], NULL,
+						fuel_gauge_thread_handler,
+						IRQF_ONESHOT, DEV_NAME, info);
+		if (ret)
+			return dev_err_probe(dev, ret, "requesting IRQ %d\n", info->irq[i]);
+	}
 
 	return 0;
 }
@@ -758,21 +739,8 @@ static const struct platform_device_id axp288_fg_id_table[] = {
 };
 MODULE_DEVICE_TABLE(platform, axp288_fg_id_table);
 
-static int axp288_fuel_gauge_remove(struct platform_device *pdev)
-{
-	struct axp288_fg_info *info = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < AXP288_FG_INTR_NUM; i++)
-		if (info->irq[i] >= 0)
-			free_irq(info->irq[i], info);
-
-	return 0;
-}
-
 static struct platform_driver axp288_fuel_gauge_driver = {
 	.probe = axp288_fuel_gauge_probe,
-	.remove = axp288_fuel_gauge_remove,
 	.id_table = axp288_fg_id_table,
 	.driver = {
 		.name = DEV_NAME,
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/7] power: supply: axp288_fuel_gauge: Take lock before updating the valid flag
  2022-01-06 11:06 [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe() Hans de Goede
                   ` (3 preceding siblings ...)
  2022-01-06 11:06 ` [PATCH 5/7] power: supply: axp288_fuel_gauge: Refactor IRQ initialization Hans de Goede
@ 2022-01-06 11:06 ` Hans de Goede
  2022-01-06 11:06 ` [PATCH 7/7] power: supply: axp288_fuel_gauge: Add a no_current_sense_res module_param Hans de Goede
  5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2022-01-06 11:06 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, linux-pm

The valid flag is protected by the mutex, so code clearing it
should take the mutex before cleating the valid flag.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index f7dce029266a..53d0e82bbb3e 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -476,7 +476,9 @@ static irqreturn_t fuel_gauge_thread_handler(int irq, void *dev)
 		dev_warn(info->dev, "Spurious Interrupt!!!\n");
 	}
 
+	mutex_lock(&info->lock);
 	info->valid = 0; /* Force updating of the cached registers */
+	mutex_unlock(&info->lock);
 
 	power_supply_changed(info->bat);
 	return IRQ_HANDLED;
@@ -486,7 +488,9 @@ static void fuel_gauge_external_power_changed(struct power_supply *psy)
 {
 	struct axp288_fg_info *info = power_supply_get_drvdata(psy);
 
+	mutex_lock(&info->lock);
 	info->valid = 0; /* Force updating of the cached registers */
+	mutex_unlock(&info->lock);
 	power_supply_changed(info->bat);
 }
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 7/7] power: supply: axp288_fuel_gauge: Add a no_current_sense_res module_param
  2022-01-06 11:06 [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe() Hans de Goede
                   ` (4 preceding siblings ...)
  2022-01-06 11:06 ` [PATCH 6/7] power: supply: axp288_fuel_gauge: Take lock before updating the valid flag Hans de Goede
@ 2022-01-06 11:06 ` Hans de Goede
  5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2022-01-06 11:06 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, linux-pm

Some boards with an AXP288 fuel-gauge appear to have a broken (approx.
2 milli-ohm instead of 10) current sense resistor.

This makes the coulomb-counter part of the fuel-gauge useless, but the
OCV based capacity reporting is still working. Add a no_current_sense_res
module_param to disable use of the coulomb-counter using parts of the
fuel-gauge to allow users to work around this.

Note this is a module parameter and not done through DMI quirks, since
this seems to be a defect on some boards, not something which all boards
of the same model share.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 33 +++++++++++++++++-------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index 53d0e82bbb3e..dcedbc59732d 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -88,6 +88,11 @@
 
 #define AXP288_REG_UPDATE_INTERVAL		(60 * HZ)
 #define AXP288_FG_INTR_NUM			6
+
+static bool no_current_sense_res;
+module_param(no_current_sense_res, bool, 0444);
+MODULE_PARM_DESC(no_current_sense_res, "No (or broken) current sense resisitor");
+
 enum {
 	QWBTU_IRQ = 0,
 	WBTU_IRQ,
@@ -137,12 +142,13 @@ static enum power_supply_property fuel_gauge_props[] = {
 	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_VOLTAGE_OCV,
-	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
+	/* The 3 props below are not used when no_current_sense_res is set */
 	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
 };
 
 static int fuel_gauge_reg_readb(struct axp288_fg_info *info, int reg)
@@ -224,7 +230,10 @@ static int fuel_gauge_update_registers(struct axp288_fg_info *info)
 		goto out;
 	info->pwr_stat = ret;
 
-	ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES);
+	if (no_current_sense_res)
+		ret = fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG);
+	else
+		ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES);
 	if (ret < 0)
 		goto out;
 	info->fg_res = ret;
@@ -233,6 +242,14 @@ static int fuel_gauge_update_registers(struct axp288_fg_info *info)
 	if (ret < 0)
 		goto out;
 
+	ret = fuel_gauge_read_12bit_word(info, AXP288_FG_OCVH_REG);
+	if (ret < 0)
+		goto out;
+	info->ocv = ret;
+
+	if (no_current_sense_res)
+		goto out_no_current_sense_res;
+
 	if (info->pwr_stat & PS_STAT_BAT_CHRG_DIR) {
 		info->d_curr = 0;
 		ret = iio_read_channel_raw(info->iio_channel[BAT_CHRG_CURR], &info->c_curr);
@@ -245,11 +262,6 @@ static int fuel_gauge_update_registers(struct axp288_fg_info *info)
 			goto out;
 	}
 
-	ret = fuel_gauge_read_12bit_word(info, AXP288_FG_OCVH_REG);
-	if (ret < 0)
-		goto out;
-	info->ocv = ret;
-
 	ret = fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG);
 	if (ret < 0)
 		goto out;
@@ -260,6 +272,7 @@ static int fuel_gauge_update_registers(struct axp288_fg_info *info)
 		goto out;
 	info->fg_des_cap1 = ret;
 
+out_no_current_sense_res:
 	info->last_updated = jiffies;
 	info->valid = 1;
 	ret = 0;
@@ -292,7 +305,7 @@ static void fuel_gauge_get_status(struct axp288_fg_info *info)
 	 * When this happens the AXP288 reports a not-charging status and
 	 * 0 mA discharge current.
 	 */
-	if (fg_res < 90 || (pwr_stat & PS_STAT_BAT_CHRG_DIR))
+	if (fg_res < 90 || (pwr_stat & PS_STAT_BAT_CHRG_DIR) || no_current_sense_res)
 		goto not_full;
 
 	if (curr == 0) {
@@ -494,7 +507,7 @@ static void fuel_gauge_external_power_changed(struct power_supply *psy)
 	power_supply_changed(info->bat);
 }
 
-static const struct power_supply_desc fuel_gauge_desc = {
+static struct power_supply_desc fuel_gauge_desc = {
 	.name			= DEV_NAME,
 	.type			= POWER_SUPPLY_TYPE_BATTERY,
 	.properties		= fuel_gauge_props,
@@ -719,6 +732,8 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 		return ret;
 
 	psy_cfg.drv_data = info;
+	if (no_current_sense_res)
+		fuel_gauge_desc.num_properties = ARRAY_SIZE(fuel_gauge_props) - 3;
 	info->bat = devm_power_supply_register(dev, &fuel_gauge_desc, &psy_cfg);
 	if (IS_ERR(info->bat)) {
 		ret = PTR_ERR(info->bat);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-01-06 11:07 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-06 11:06 [PATCH 1/7] power: supply: axp288_fuel_gauge: Add dev helper var to probe() Hans de Goede
2022-01-06 11:06 ` [PATCH 2/7] power: supply: axp288_fuel_gauge: Add axp288_fuel_gauge_read_initial_regs() Hans de Goede
2022-01-06 11:06 ` [PATCH 3/7] power: supply: axp288_fuel_gauge: Use devm_add_action_or_reset() for iio chan release Hans de Goede
2022-01-06 11:06 ` [PATCH 4/7] power: supply: axp288_fuel_gauge: Use devm_power_supply_register() Hans de Goede
2022-01-06 11:06 ` [PATCH 5/7] power: supply: axp288_fuel_gauge: Refactor IRQ initialization Hans de Goede
2022-01-06 11:06 ` [PATCH 6/7] power: supply: axp288_fuel_gauge: Take lock before updating the valid flag Hans de Goede
2022-01-06 11:06 ` [PATCH 7/7] power: supply: axp288_fuel_gauge: Add a no_current_sense_res module_param Hans de Goede

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.