140 lines
4.2 KiB
Diff
140 lines
4.2 KiB
Diff
|
From 809e2feab1749edf87f46cfa9eccbe911dcc3350 Mon Sep 17 00:00:00 2001
|
||
|
From: Samuel Holland <samuel@sholland.org>
|
||
|
Date: Sat, 29 Feb 2020 01:04:17 -0600
|
||
|
Subject: [PATCH 228/464] power: supply: axp20x_battery: Send uevents for
|
||
|
status changes
|
||
|
|
||
|
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||
|
---
|
||
|
drivers/power/supply/axp20x_battery.c | 55 ++++++++++++++++++++++++++-
|
||
|
1 file changed, 53 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
|
||
|
index 6b51005d8551..3331910f46a6 100644
|
||
|
--- a/drivers/power/supply/axp20x_battery.c
|
||
|
+++ b/drivers/power/supply/axp20x_battery.c
|
||
|
@@ -57,14 +57,22 @@
|
||
|
|
||
|
#define AXP20X_V_OFF_MASK GENMASK(2, 0)
|
||
|
|
||
|
+#define DRVNAME "axp20x-battery-power-supply"
|
||
|
+
|
||
|
struct axp20x_batt_ps;
|
||
|
|
||
|
+struct axp_irq_data {
|
||
|
+ const char *name;
|
||
|
+ irq_handler_t handler;
|
||
|
+};
|
||
|
+
|
||
|
struct axp_data {
|
||
|
int ccc_scale;
|
||
|
int ccc_offset;
|
||
|
bool has_fg_valid;
|
||
|
int (*get_max_voltage)(struct axp20x_batt_ps *batt, int *val);
|
||
|
int (*set_max_voltage)(struct axp20x_batt_ps *batt, int val);
|
||
|
+ const struct axp_irq_data *irqs;
|
||
|
};
|
||
|
|
||
|
struct axp20x_batt_ps {
|
||
|
@@ -548,11 +556,31 @@ static const struct power_supply_desc axp20x_batt_ps_desc = {
|
||
|
.set_property = axp20x_battery_set_prop,
|
||
|
};
|
||
|
|
||
|
+static irqreturn_t axp20x_battery_changed_irq(int irq, void *devid)
|
||
|
+{
|
||
|
+ struct axp20x_batt_ps *axp20x_batt = devid;
|
||
|
+
|
||
|
+ power_supply_changed(axp20x_batt->batt);
|
||
|
+
|
||
|
+ return IRQ_HANDLED;
|
||
|
+}
|
||
|
+
|
||
|
+static const struct axp_irq_data axp20x_irqs[] = {
|
||
|
+ { "BATT_PLUGIN", axp20x_battery_changed_irq },
|
||
|
+ { "BATT_REMOVAL", axp20x_battery_changed_irq },
|
||
|
+ { "BATT_HEALTH_DEAD", axp20x_battery_changed_irq },
|
||
|
+ { "BATT_HEALTH_GOOD", axp20x_battery_changed_irq },
|
||
|
+ { "BATT_CHARGING", axp20x_battery_changed_irq },
|
||
|
+ { "BATT_CHARGING_DONE", axp20x_battery_changed_irq },
|
||
|
+ {}
|
||
|
+};
|
||
|
+
|
||
|
static const struct axp_data axp209_data = {
|
||
|
.ccc_scale = 100000,
|
||
|
.ccc_offset = 300000,
|
||
|
.get_max_voltage = axp20x_battery_get_max_voltage,
|
||
|
.set_max_voltage = axp20x_battery_set_max_voltage,
|
||
|
+ .irqs = axp20x_irqs,
|
||
|
};
|
||
|
|
||
|
static const struct axp_data axp221_data = {
|
||
|
@@ -561,6 +589,7 @@ static const struct axp_data axp221_data = {
|
||
|
.has_fg_valid = true,
|
||
|
.get_max_voltage = axp22x_battery_get_max_voltage,
|
||
|
.set_max_voltage = axp22x_battery_set_max_voltage,
|
||
|
+ .irqs = axp20x_irqs,
|
||
|
};
|
||
|
|
||
|
static const struct axp_data axp813_data = {
|
||
|
@@ -569,6 +598,7 @@ static const struct axp_data axp813_data = {
|
||
|
.has_fg_valid = true,
|
||
|
.get_max_voltage = axp813_battery_get_max_voltage,
|
||
|
.set_max_voltage = axp20x_battery_set_max_voltage,
|
||
|
+ .irqs = axp20x_irqs,
|
||
|
};
|
||
|
|
||
|
static const struct of_device_id axp20x_battery_ps_id[] = {
|
||
|
@@ -587,11 +617,13 @@ MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);
|
||
|
|
||
|
static int axp20x_power_probe(struct platform_device *pdev)
|
||
|
{
|
||
|
+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
|
||
|
struct axp20x_batt_ps *axp20x_batt;
|
||
|
struct power_supply_config psy_cfg = {};
|
||
|
struct power_supply_battery_info *info;
|
||
|
struct device *dev = &pdev->dev;
|
||
|
- int ret;
|
||
|
+ const struct axp_irq_data *irq_data;
|
||
|
+ int irq, ret;
|
||
|
|
||
|
if (!of_device_is_available(pdev->dev.of_node))
|
||
|
return -ENODEV;
|
||
|
@@ -665,6 +697,25 @@ static int axp20x_power_probe(struct platform_device *pdev)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ /* Request irqs after registering, as irqs may trigger immediately */
|
||
|
+ for (irq_data = axp20x_batt->data->irqs; irq_data->name; irq_data++) {
|
||
|
+ irq = platform_get_irq_byname(pdev, irq_data->name);
|
||
|
+ if (irq < 0) {
|
||
|
+ dev_err(&pdev->dev, "No IRQ for %s: %d\n",
|
||
|
+ irq_data->name, irq);
|
||
|
+ return irq;
|
||
|
+ }
|
||
|
+ irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
|
||
|
+ ret = devm_request_any_context_irq(&pdev->dev, irq,
|
||
|
+ irq_data->handler, 0,
|
||
|
+ DRVNAME, axp20x_batt);
|
||
|
+ if (ret < 0) {
|
||
|
+ dev_err(&pdev->dev, "Error requesting %s IRQ: %d\n",
|
||
|
+ irq_data->name, ret);
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
/*
|
||
|
* Update max CCC to a valid value if battery info is present or set it
|
||
|
* to current register value by default.
|
||
|
@@ -731,7 +782,7 @@ static int axp20x_power_probe(struct platform_device *pdev)
|
||
|
static struct platform_driver axp20x_batt_driver = {
|
||
|
.probe = axp20x_power_probe,
|
||
|
.driver = {
|
||
|
- .name = "axp20x-battery-power-supply",
|
||
|
+ .name = DRVNAME,
|
||
|
.of_match_table = axp20x_battery_ps_id,
|
||
|
},
|
||
|
};
|
||
|
--
|
||
|
2.34.1
|
||
|
|