All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <4101467707611@web7h.yandex.ru>

diff --git a/a/1.txt b/N1/1.txt
index 46acd5f..26b8a05 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,9 +1,9 @@
 
 
-05.07.2016, 13:26, "Michael Haas" <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>:
+05.07.2016, 13:26, "Michael Haas" <michael.haas@mailbox.org>:
 > Hi,
 >
-> nice work! Is this in any way related to Bruno Prémonts driver for the
+> nice work! Is this in any way related to Bruno Pr?monts driver for the
 > axp20x?
 >
 > I've got a reworked version of that lying around, but it's not quite
@@ -13,326 +13,321 @@
 > Michael
 >
 > On 01.07.2016 11:29, Icenowy Zheng wrote:
->>  This driver is the battery power supply driver of axp20x PMIC. Currently
->>  it supports only AXP22x variants.
+>> ?This driver is the battery power supply driver of axp20x PMIC. Currently
+>> ?it supports only AXP22x variants.
 >>
->>  Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
->>  ---
->>    drivers/mfd/axp20x.c | 14 +++
->>    drivers/power/Makefile | 1 +
->>    drivers/power/axp20x_battery.c | 254 +++++++++++++++++++++++++++++++++++++++++
->>    3 files changed, 269 insertions(+)
->>    create mode 100644 drivers/power/axp20x_battery.c
+>> ?Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
+>> ?---
+>> ???drivers/mfd/axp20x.c | 14 +++
+>> ???drivers/power/Makefile | 1 +
+>> ???drivers/power/axp20x_battery.c | 254 +++++++++++++++++++++++++++++++++++++++++
+>> ???3 files changed, 269 insertions(+)
+>> ???create mode 100644 drivers/power/axp20x_battery.c
 >>
->>  diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
->>  index cee5288..064e5015 100644
->>  --- a/drivers/mfd/axp20x.c
->>  +++ b/drivers/mfd/axp20x.c
->>  @@ -166,6 +166,15 @@ static struct resource axp22x_usb_power_supply_resources[] = {
->>            DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
->>    };
+>> ?diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
+>> ?index cee5288..064e5015 100644
+>> ?--- a/drivers/mfd/axp20x.c
+>> ?+++ b/drivers/mfd/axp20x.c
+>> ?@@ -166,6 +166,15 @@ static struct resource axp22x_usb_power_supply_resources[] = {
+>> ???????????DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
+>> ???};
 >>
->>  +static struct resource axp22x_battery_resources[] = {
->>  + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_PLUGIN, "BATT_PLUGIN"),
->>  + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_REMOVAL, "BATT_REMOVAL"),
->>  + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_ENT_ACT_MODE, "BATT_ENT_ACT_MODE"),
->>  + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_EXIT_ACT_MODE, "BATT_EXIT_ACT_MODE"),
->>  + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG, "CHARG"),
->>  + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG_DONE, "CHARG_DONE"),
->>  +};
->>  +
->>    static struct resource axp22x_pek_resources[] = {
->>            {
->>                    .name = "PEK_DBR",
->>  @@ -538,6 +547,11 @@ static struct mfd_cell axp22x_cells[] = {
->>                    .of_compatible = "x-powers,axp202-usb-power-supply",
->>                    .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),
->>                    .resources = axp22x_usb_power_supply_resources,
->>  + }, {
->>  + .name = "axp20x-battery",
->>  + .of_compatible = "x-powers,axp202-battery",
->>  + .num_resources = ARRAY_SIZE(axp22x_battery_resources),
->>  + .resources = axp22x_battery_resources,
->>            },
->>    };
+>> ?+static struct resource axp22x_battery_resources[] = {
+>> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_PLUGIN, "BATT_PLUGIN"),
+>> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_REMOVAL, "BATT_REMOVAL"),
+>> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_ENT_ACT_MODE, "BATT_ENT_ACT_MODE"),
+>> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_EXIT_ACT_MODE, "BATT_EXIT_ACT_MODE"),
+>> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG, "CHARG"),
+>> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG_DONE, "CHARG_DONE"),
+>> ?+};
+>> ?+
+>> ???static struct resource axp22x_pek_resources[] = {
+>> ???????????{
+>> ???????????????????.name = "PEK_DBR",
+>> ?@@ -538,6 +547,11 @@ static struct mfd_cell axp22x_cells[] = {
+>> ???????????????????.of_compatible = "x-powers,axp202-usb-power-supply",
+>> ???????????????????.num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),
+>> ???????????????????.resources = axp22x_usb_power_supply_resources,
+>> ?+ }, {
+>> ?+ .name = "axp20x-battery",
+>> ?+ .of_compatible = "x-powers,axp202-battery",
+>> ?+ .num_resources = ARRAY_SIZE(axp22x_battery_resources),
+>> ?+ .resources = axp22x_battery_resources,
+>> ???????????},
+>> ???};
 >>
->>  diff --git a/drivers/power/Makefile b/drivers/power/Makefile
->>  index e46b75d..1452d23 100644
->>  --- a/drivers/power/Makefile
->>  +++ b/drivers/power/Makefile
->>  @@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o
->>    obj-$(CONFIG_PDA_POWER) += pda_power.o
->>    obj-$(CONFIG_APM_POWER) += apm_power.o
->>    obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o
->>  +obj-$(CONFIG_AXP20X_POWER) += axp20x_battery.o
->>    obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
->>    obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
->>    obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
->>  diff --git a/drivers/power/axp20x_battery.c b/drivers/power/axp20x_battery.c
->>  new file mode 100644
->>  index 0000000..8fac2cd
->>  --- /dev/null
->>  +++ b/drivers/power/axp20x_battery.c
->>  @@ -0,0 +1,254 @@
->>  +/*
->>  + * AXP20x PMIC battery status driver
->>  + *
->>  + * Copyright (C) 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
->>  + * Copyright (C) 2015 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
->>  + * Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.org>
->>  + *
->>  + * This program is free software; you can redistribute it and/or modify it
->>  + * under the terms of the GNU General Public License as published by the
->>  + * Free Software Foundation; either version 2 of the License, or (at your
->>  + * option) any later version.
->>  + */
->>  +
->>  +#include <linux/device.h>
->>  +#include <linux/init.h>
->>  +#include <linux/interrupt.h>
->>  +#include <linux/kernel.h>
->>  +#include <linux/mfd/axp20x.h>
->>  +#include <linux/module.h>
->>  +#include <linux/of.h>
->>  +#include <linux/platform_device.h>
->>  +#include <linux/power_supply.h>
->>  +#include <linux/regmap.h>
->>  +#include <linux/slab.h>
->>  +
->>  +#define DRVNAME "axp20x-battery"
->>  +
->>  +#define AXP20X_PWR_STATUS_ACIN_USED BIT(6)
->>  +#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
->>  +#define AXP20X_PWR_STATUS_BAT_DIRECTION BIT(2)
->>  +
->>  +#define AXP20X_OP_MODE_CHARGING BIT(6)
->>  +#define AXP20X_OP_MODE_BATTERY_PRESENT BIT(5)
->>  +#define AXP20X_OP_MODE_BATTERY_ACTIVE BIT(3)
->>  +
->>  +#define AXP20X_CAPACITY_CORRECT BIT(7)
->>  +
->>  +struct axp20x_battery {
->>  + struct axp20x_dev *axp20x;
->>  + struct regmap *regmap;
->>  + struct power_supply *supply;
->>  +};
->>  +
->>  +static irqreturn_t axp20x_battery_irq(int irq, void *devid)
->>  +{
->>  + struct axp20x_battery *power = devid;
->>  +
->>  + power_supply_changed(power->supply);
->>  +
->>  + return IRQ_HANDLED;
->>  +}
->>  +
->>  +static int axp20x_battery_get_property(struct power_supply *psy,
->>  + enum power_supply_property psp, union power_supply_propval *val)
->>  +{
->>  + struct axp20x_battery *power = power_supply_get_drvdata(psy);
->>  + unsigned int input, op_mode, capacity, dh, dl;
->>  + int ret, ext;
->>  +
->>  + /* All the properties below need the input-status reg value */
->>  + ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);
->>  + if (ret)
->>  + return ret;
->>  +
->>  + ret = regmap_read(power->regmap, AXP20X_PWR_OP_MODE, &op_mode);
->>  + if (ret)
->>  + return ret;
->>  +
->>  + switch (psp) {
->>  + case POWER_SUPPLY_PROP_HEALTH:
->>  + if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {
->>  + val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
->>  + break;
->>  + }
->>  +
->>  + val->intval = POWER_SUPPLY_HEALTH_GOOD;
->>  +
->>  + if (op_mode & AXP20X_OP_MODE_BATTERY_ACTIVE) {
->>  + /* AXP20X is now trying to re-activate the battery */
->>  + val->intval = POWER_SUPPLY_HEALTH_DEAD;
->>  + break;
->>  + }
->>  + break;
->>  + case POWER_SUPPLY_PROP_PRESENT:
->>  + val->intval = !!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT);
->>  + break;
->>  + case POWER_SUPPLY_PROP_CAPACITY:
->>  + ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);
->>  + if (ret)
->>  + return ret;
->>  + if (capacity & AXP20X_CAPACITY_CORRECT)
->>  + val->intval = capacity & (~AXP20X_CAPACITY_CORRECT);
->>  + else
->>  + return -EIO;
->>  + /* from axp_capchange function of Allwinner 3.4 driver */
->>  + if (val->intval == 127)
->>  + val->intval = 100;
->>  + break;
->>  + case POWER_SUPPLY_PROP_STATUS:
->>  + if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {
->>  + val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
->>  + break;
->>  + }
->>  +
->>  + ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);
->>  + if (ret)
->>  + return ret;
->>  +
->>  + ext = (input & AXP20X_PWR_STATUS_ACIN_USED) ||
->>  + (input & AXP20X_PWR_STATUS_VBUS_USED);
->>  +
->>  + if (op_mode & AXP20X_OP_MODE_CHARGING)
->>  + val->intval = POWER_SUPPLY_STATUS_CHARGING;
->>  + else if (!(input & AXP20X_PWR_STATUS_BAT_DIRECTION) && !ext)
->>  + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
->>  + else if (capacity == (100 | AXP20X_CAPACITY_CORRECT) ||
->>  + capacity == (127 | AXP20X_CAPACITY_CORRECT))
->>  + val->intval = POWER_SUPPLY_STATUS_FULL;
->>  + else
->>  + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
->>  + break;
->>  + case POWER_SUPPLY_PROP_CURRENT_NOW:
->>  + ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_H, &dh);
->>  + if (ret)
->>  + return ret;
->>  + ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_L, &dl);
->>  + if (ret)
->>  + return ret;
->>  + /* it's a 12 bit integer, high 8-bit is stored in dh */
->>  + val->intval = dh << 4 | dl >> 4;
->>  + break;
->>  + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
->>  + ret = regmap_read(power->regmap, AXP20X_BATT_V_H, &dh);
->>  + if (ret)
->>  + return ret;
->>  + ret = regmap_read(power->regmap, AXP20X_BATT_V_L, &dl);
->>  + if (ret)
->>  + return ret;
->>  + /* it's a 12 bit integer, high 8-bit is stored in dh */
->>  + val->intval = dh << 4 | dl >> 4;
->>  + /* The formula below is from axp22_vbat_to_mV function
->>  + * of Allwinner 3.4 kernel.
->>  + */
->>  + val->intval = val->intval * 1100 / 1000;
->>  + break;
->>  + default:
->>  + return -EINVAL;
->>  + }
->>  +
->>  + return 0;
->>  +}
->>  +
->>  +static enum power_supply_property axp22x_battery_properties[] = {
->>  + POWER_SUPPLY_PROP_CAPACITY,
->>  + POWER_SUPPLY_PROP_HEALTH,
->>  + POWER_SUPPLY_PROP_PRESENT,
->>  + POWER_SUPPLY_PROP_STATUS,
->>  + POWER_SUPPLY_PROP_CURRENT_NOW,
->>  + POWER_SUPPLY_PROP_VOLTAGE_NOW,
->>  +};
->>  +
->>  +static const struct power_supply_desc axp22x_battery_desc = {
->>  + .name = "axp20x-battery",
->>  + .type = POWER_SUPPLY_TYPE_BATTERY,
->>  + .properties = axp22x_battery_properties,
->>  + .num_properties = ARRAY_SIZE(axp22x_battery_properties),
->>  + .get_property = axp20x_battery_get_property,
->>  +};
->>  +
->>  +static int axp20x_battery_probe(struct platform_device *pdev)
->>  +{
->>  + struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
->>  + struct power_supply_config psy_cfg = {};
->>  + struct axp20x_battery *power;
->>  + static const char * const axp22x_irq_names[] = {
->>  + "BATT_PLUGIN", "BATT_REMOVAL", "BATT_ENT_ACT_MODE",
->>  + "BATT_EXIT_ACT_MODE", "CHARG", "CHARG_DONE", NULL };
->>  + static const char * const *irq_names;
->>  + const struct power_supply_desc *battery_desc;
->>  + int i, irq, ret;
->>  +
->>  + if (!of_device_is_available(pdev->dev.of_node))
->>  + return -ENODEV;
->>  +
->>  + if (!axp20x) {
->>  + dev_err(&pdev->dev, "Parent drvdata not set\n");
->>  + return -EINVAL;
->>  + }
->>  +
->>  + power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL);
->>  + if (!power)
->>  + return -ENOMEM;
->>  +
->>  + power->axp20x = axp20x;
->>  + power->regmap = axp20x->regmap;
->>  +
->>  + switch (power->axp20x->variant) {
->>  + case AXP221_ID:
->>  + case AXP223_ID:
->>  + battery_desc = &axp22x_battery_desc;
->>  + irq_names = axp22x_irq_names;
->>  + break;
->>  + default:
->>  + dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
->>  + axp20x->variant);
->>  + return -EINVAL;
->>  + }
->>  +
->>  + psy_cfg.of_node = pdev->dev.of_node;
->>  + psy_cfg.drv_data = power;
->>  +
->>  + power->supply = devm_power_supply_register(&pdev->dev, battery_desc,
->>  + &psy_cfg);
->>  + if (IS_ERR(power->supply))
->>  + return PTR_ERR(power->supply);
->>  +
->>  + /* Request irqs after registering, as irqs may trigger immediately */
->>  + for (i = 0; irq_names[i]; i++) {
->>  + irq = platform_get_irq_byname(pdev, irq_names[i]);
->>  + if (irq < 0) {
->>  + dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
->>  + irq_names[i], irq);
->>  + continue;
->>  + }
->>  + irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
->>  + ret = devm_request_any_context_irq(&pdev->dev, irq,
->>  + axp20x_battery_irq, 0, DRVNAME, power);
->>  + if (ret < 0)
->>  + dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n",
->>  + irq_names[i], ret);
->>  + }
->>  +
->>  + return 0;
->>  +}
->>  +
->>  +static const struct of_device_id axp20x_battery_match[] = {
->>  + { .compatible = "x-powers,axp202-battery" },
->>  + { }
->>  +};
->>  +MODULE_DEVICE_TABLE(of, axp20x_battery_match);
->>  +
->>  +static struct platform_driver axp20x_battery_driver = {
->>  + .probe = axp20x_battery_probe,
->>  + .driver = {
->>  + .name = DRVNAME,
->>  + .of_match_table = axp20x_battery_match,
->>  + },
->>  +};
->>  +
->>  +module_platform_driver(axp20x_battery_driver);
->>  +
->>  +MODULE_AUTHOR("Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>");
->>  +MODULE_DESCRIPTION("AXP20x PMIC battery status driver");
->>  +MODULE_LICENSE("GPL");
+>> ?diff --git a/drivers/power/Makefile b/drivers/power/Makefile
+>> ?index e46b75d..1452d23 100644
+>> ?--- a/drivers/power/Makefile
+>> ?+++ b/drivers/power/Makefile
+>> ?@@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o
+>> ???obj-$(CONFIG_PDA_POWER) += pda_power.o
+>> ???obj-$(CONFIG_APM_POWER) += apm_power.o
+>> ???obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o
+>> ?+obj-$(CONFIG_AXP20X_POWER) += axp20x_battery.o
+>> ???obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
+>> ???obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
+>> ???obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
+>> ?diff --git a/drivers/power/axp20x_battery.c b/drivers/power/axp20x_battery.c
+>> ?new file mode 100644
+>> ?index 0000000..8fac2cd
+>> ?--- /dev/null
+>> ?+++ b/drivers/power/axp20x_battery.c
+>> ?@@ -0,0 +1,254 @@
+>> ?+/*
+>> ?+ * AXP20x PMIC battery status driver
+>> ?+ *
+>> ?+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+>> ?+ * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
+>> ?+ * Copyright (C) 2014 Bruno Pr?mont <bonbons@linux-vserver.org>
+>> ?+ *
+>> ?+ * This program is free software; you can redistribute it and/or modify it
+>> ?+ * under the terms of the GNU General Public License as published by the
+>> ?+ * Free Software Foundation; either version 2 of the License, or (at your
+>> ?+ * option) any later version.
+>> ?+ */
+>> ?+
+>> ?+#include <linux/device.h>
+>> ?+#include <linux/init.h>
+>> ?+#include <linux/interrupt.h>
+>> ?+#include <linux/kernel.h>
+>> ?+#include <linux/mfd/axp20x.h>
+>> ?+#include <linux/module.h>
+>> ?+#include <linux/of.h>
+>> ?+#include <linux/platform_device.h>
+>> ?+#include <linux/power_supply.h>
+>> ?+#include <linux/regmap.h>
+>> ?+#include <linux/slab.h>
+>> ?+
+>> ?+#define DRVNAME "axp20x-battery"
+>> ?+
+>> ?+#define AXP20X_PWR_STATUS_ACIN_USED BIT(6)
+>> ?+#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
+>> ?+#define AXP20X_PWR_STATUS_BAT_DIRECTION BIT(2)
+>> ?+
+>> ?+#define AXP20X_OP_MODE_CHARGING BIT(6)
+>> ?+#define AXP20X_OP_MODE_BATTERY_PRESENT BIT(5)
+>> ?+#define AXP20X_OP_MODE_BATTERY_ACTIVE BIT(3)
+>> ?+
+>> ?+#define AXP20X_CAPACITY_CORRECT BIT(7)
+>> ?+
+>> ?+struct axp20x_battery {
+>> ?+ struct axp20x_dev *axp20x;
+>> ?+ struct regmap *regmap;
+>> ?+ struct power_supply *supply;
+>> ?+};
+>> ?+
+>> ?+static irqreturn_t axp20x_battery_irq(int irq, void *devid)
+>> ?+{
+>> ?+ struct axp20x_battery *power = devid;
+>> ?+
+>> ?+ power_supply_changed(power->supply);
+>> ?+
+>> ?+ return IRQ_HANDLED;
+>> ?+}
+>> ?+
+>> ?+static int axp20x_battery_get_property(struct power_supply *psy,
+>> ?+ enum power_supply_property psp, union power_supply_propval *val)
+>> ?+{
+>> ?+ struct axp20x_battery *power = power_supply_get_drvdata(psy);
+>> ?+ unsigned int input, op_mode, capacity, dh, dl;
+>> ?+ int ret, ext;
+>> ?+
+>> ?+ /* All the properties below need the input-status reg value */
+>> ?+ ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+
+>> ?+ ret = regmap_read(power->regmap, AXP20X_PWR_OP_MODE, &op_mode);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+
+>> ?+ switch (psp) {
+>> ?+ case POWER_SUPPLY_PROP_HEALTH:
+>> ?+ if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {
+>> ?+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+>> ?+ break;
+>> ?+ }
+>> ?+
+>> ?+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+>> ?+
+>> ?+ if (op_mode & AXP20X_OP_MODE_BATTERY_ACTIVE) {
+>> ?+ /* AXP20X is now trying to re-activate the battery */
+>> ?+ val->intval = POWER_SUPPLY_HEALTH_DEAD;
+>> ?+ break;
+>> ?+ }
+>> ?+ break;
+>> ?+ case POWER_SUPPLY_PROP_PRESENT:
+>> ?+ val->intval = !!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT);
+>> ?+ break;
+>> ?+ case POWER_SUPPLY_PROP_CAPACITY:
+>> ?+ ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+ if (capacity & AXP20X_CAPACITY_CORRECT)
+>> ?+ val->intval = capacity & (~AXP20X_CAPACITY_CORRECT);
+>> ?+ else
+>> ?+ return -EIO;
+>> ?+ /* from axp_capchange function of Allwinner 3.4 driver */
+>> ?+ if (val->intval == 127)
+>> ?+ val->intval = 100;
+>> ?+ break;
+>> ?+ case POWER_SUPPLY_PROP_STATUS:
+>> ?+ if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {
+>> ?+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+>> ?+ break;
+>> ?+ }
+>> ?+
+>> ?+ ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+
+>> ?+ ext = (input & AXP20X_PWR_STATUS_ACIN_USED) ||
+>> ?+ (input & AXP20X_PWR_STATUS_VBUS_USED);
+>> ?+
+>> ?+ if (op_mode & AXP20X_OP_MODE_CHARGING)
+>> ?+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+>> ?+ else if (!(input & AXP20X_PWR_STATUS_BAT_DIRECTION) && !ext)
+>> ?+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+>> ?+ else if (capacity == (100 | AXP20X_CAPACITY_CORRECT) ||
+>> ?+ capacity == (127 | AXP20X_CAPACITY_CORRECT))
+>> ?+ val->intval = POWER_SUPPLY_STATUS_FULL;
+>> ?+ else
+>> ?+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+>> ?+ break;
+>> ?+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+>> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_H, &dh);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_L, &dl);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+ /* it's a 12 bit integer, high 8-bit is stored in dh */
+>> ?+ val->intval = dh << 4 | dl >> 4;
+>> ?+ break;
+>> ?+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+>> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_V_H, &dh);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_V_L, &dl);
+>> ?+ if (ret)
+>> ?+ return ret;
+>> ?+ /* it's a 12 bit integer, high 8-bit is stored in dh */
+>> ?+ val->intval = dh << 4 | dl >> 4;
+>> ?+ /* The formula below is from axp22_vbat_to_mV function
+>> ?+ * of Allwinner 3.4 kernel.
+>> ?+ */
+>> ?+ val->intval = val->intval * 1100 / 1000;
+>> ?+ break;
+>> ?+ default:
+>> ?+ return -EINVAL;
+>> ?+ }
+>> ?+
+>> ?+ return 0;
+>> ?+}
+>> ?+
+>> ?+static enum power_supply_property axp22x_battery_properties[] = {
+>> ?+ POWER_SUPPLY_PROP_CAPACITY,
+>> ?+ POWER_SUPPLY_PROP_HEALTH,
+>> ?+ POWER_SUPPLY_PROP_PRESENT,
+>> ?+ POWER_SUPPLY_PROP_STATUS,
+>> ?+ POWER_SUPPLY_PROP_CURRENT_NOW,
+>> ?+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+>> ?+};
+>> ?+
+>> ?+static const struct power_supply_desc axp22x_battery_desc = {
+>> ?+ .name = "axp20x-battery",
+>> ?+ .type = POWER_SUPPLY_TYPE_BATTERY,
+>> ?+ .properties = axp22x_battery_properties,
+>> ?+ .num_properties = ARRAY_SIZE(axp22x_battery_properties),
+>> ?+ .get_property = axp20x_battery_get_property,
+>> ?+};
+>> ?+
+>> ?+static int axp20x_battery_probe(struct platform_device *pdev)
+>> ?+{
+>> ?+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+>> ?+ struct power_supply_config psy_cfg = {};
+>> ?+ struct axp20x_battery *power;
+>> ?+ static const char * const axp22x_irq_names[] = {
+>> ?+ "BATT_PLUGIN", "BATT_REMOVAL", "BATT_ENT_ACT_MODE",
+>> ?+ "BATT_EXIT_ACT_MODE", "CHARG", "CHARG_DONE", NULL };
+>> ?+ static const char * const *irq_names;
+>> ?+ const struct power_supply_desc *battery_desc;
+>> ?+ int i, irq, ret;
+>> ?+
+>> ?+ if (!of_device_is_available(pdev->dev.of_node))
+>> ?+ return -ENODEV;
+>> ?+
+>> ?+ if (!axp20x) {
+>> ?+ dev_err(&pdev->dev, "Parent drvdata not set\n");
+>> ?+ return -EINVAL;
+>> ?+ }
+>> ?+
+>> ?+ power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL);
+>> ?+ if (!power)
+>> ?+ return -ENOMEM;
+>> ?+
+>> ?+ power->axp20x = axp20x;
+>> ?+ power->regmap = axp20x->regmap;
+>> ?+
+>> ?+ switch (power->axp20x->variant) {
+>> ?+ case AXP221_ID:
+>> ?+ case AXP223_ID:
+>> ?+ battery_desc = &axp22x_battery_desc;
+>> ?+ irq_names = axp22x_irq_names;
+>> ?+ break;
+>> ?+ default:
+>> ?+ dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
+>> ?+ axp20x->variant);
+>> ?+ return -EINVAL;
+>> ?+ }
+>> ?+
+>> ?+ psy_cfg.of_node = pdev->dev.of_node;
+>> ?+ psy_cfg.drv_data = power;
+>> ?+
+>> ?+ power->supply = devm_power_supply_register(&pdev->dev, battery_desc,
+>> ?+ &psy_cfg);
+>> ?+ if (IS_ERR(power->supply))
+>> ?+ return PTR_ERR(power->supply);
+>> ?+
+>> ?+ /* Request irqs after registering, as irqs may trigger immediately */
+>> ?+ for (i = 0; irq_names[i]; i++) {
+>> ?+ irq = platform_get_irq_byname(pdev, irq_names[i]);
+>> ?+ if (irq < 0) {
+>> ?+ dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
+>> ?+ irq_names[i], irq);
+>> ?+ continue;
+>> ?+ }
+>> ?+ irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
+>> ?+ ret = devm_request_any_context_irq(&pdev->dev, irq,
+>> ?+ axp20x_battery_irq, 0, DRVNAME, power);
+>> ?+ if (ret < 0)
+>> ?+ dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n",
+>> ?+ irq_names[i], ret);
+>> ?+ }
+>> ?+
+>> ?+ return 0;
+>> ?+}
+>> ?+
+>> ?+static const struct of_device_id axp20x_battery_match[] = {
+>> ?+ { .compatible = "x-powers,axp202-battery" },
+>> ?+ { }
+>> ?+};
+>> ?+MODULE_DEVICE_TABLE(of, axp20x_battery_match);
+>> ?+
+>> ?+static struct platform_driver axp20x_battery_driver = {
+>> ?+ .probe = axp20x_battery_probe,
+>> ?+ .driver = {
+>> ?+ .name = DRVNAME,
+>> ?+ .of_match_table = axp20x_battery_match,
+>> ?+ },
+>> ?+};
+>> ?+
+>> ?+module_platform_driver(axp20x_battery_driver);
+>> ?+
+>> ?+MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.xyz>");
+>> ?+MODULE_DESCRIPTION("AXP20x PMIC battery status driver");
+>> ?+MODULE_LICENSE("GPL");
 
 Therotically, it can run on axp20x. However, I have currently no test device. (Still waiting for my C.H.I.P.)
 So I can only promise it to run on axp22x.
-
--- 
-You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
-To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
-For more options, visit https://groups.google.com/d/optout.
diff --git a/a/content_digest b/N1/content_digest
index 256a5e5..58b4f69 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,32 +1,18 @@
  "ref\020160701092926.32005-1-icenowy@aosc.xyz\0"
  "ref\020160701092926.32005-2-icenowy@aosc.xyz\0"
  "ref\0577B44FD.6040404@mailbox.org\0"
- "ref\0577B44FD.6040404-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org\0"
- "From\0Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>\0"
- "Subject\0Re: [PATCH 2/4] power: add axp20x-battery driver\0"
+ "From\0icenowy@aosc.xyz (Icenowy Zheng)\0"
+ "Subject\0[linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver\0"
  "Date\0Tue, 05 Jul 2016 16:33:31 +0800\0"
- "To\0Michael Haas <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>"
-  wens-jdAy2FN1RRM@public.gmane.org <wens-jdAy2FN1RRM@public.gmane.org>
-  maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
-  sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
-  dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org <dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
- " dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org <dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>\0"
- "Cc\0robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>"
-  mark.rutland-5wv7dgnIgG8@public.gmane.org <mark.rutland-5wv7dgnIgG8@public.gmane.org>
-  linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>
-  devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org <devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
-  linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org <linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
-  linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
-  linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org <linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
- " linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org <linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org>\0"
+ "To\0linux-arm-kernel@lists.infradead.org\0"
  "\00:1\0"
  "b\0"
  "\n"
  "\n"
- "05.07.2016, 13:26, \"Michael Haas\" <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>:\n"
+ "05.07.2016, 13:26, \"Michael Haas\" <michael.haas@mailbox.org>:\n"
  "> Hi,\n"
  ">\n"
- "> nice work! Is this in any way related to Bruno Pr\303\251monts driver for the\n"
+ "> nice work! Is this in any way related to Bruno Pr?monts driver for the\n"
  "> axp20x?\n"
  ">\n"
  "> I've got a reworked version of that lying around, but it's not quite\n"
@@ -36,328 +22,323 @@
  "> Michael\n"
  ">\n"
  "> On 01.07.2016 11:29, Icenowy Zheng wrote:\n"
- ">> \302\240This driver is the battery power supply driver of axp20x PMIC. Currently\n"
- ">> \302\240it supports only AXP22x variants.\n"
+ ">> ?This driver is the battery power supply driver of axp20x PMIC. Currently\n"
+ ">> ?it supports only AXP22x variants.\n"
  ">>\n"
- ">> \302\240Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>\n"
- ">> \302\240---\n"
- ">> \302\240\302\240\302\240drivers/mfd/axp20x.c | 14 +++\n"
- ">> \302\240\302\240\302\240drivers/power/Makefile | 1 +\n"
- ">> \302\240\302\240\302\240drivers/power/axp20x_battery.c | 254 +++++++++++++++++++++++++++++++++++++++++\n"
- ">> \302\240\302\240\302\2403 files changed, 269 insertions(+)\n"
- ">> \302\240\302\240\302\240create mode 100644 drivers/power/axp20x_battery.c\n"
+ ">> ?Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>\n"
+ ">> ?---\n"
+ ">> ???drivers/mfd/axp20x.c | 14 +++\n"
+ ">> ???drivers/power/Makefile | 1 +\n"
+ ">> ???drivers/power/axp20x_battery.c | 254 +++++++++++++++++++++++++++++++++++++++++\n"
+ ">> ???3 files changed, 269 insertions(+)\n"
+ ">> ???create mode 100644 drivers/power/axp20x_battery.c\n"
  ">>\n"
- ">> \302\240diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c\n"
- ">> \302\240index cee5288..064e5015 100644\n"
- ">> \302\240--- a/drivers/mfd/axp20x.c\n"
- ">> \302\240+++ b/drivers/mfd/axp20x.c\n"
- ">> \302\240@@ -166,6 +166,15 @@ static struct resource axp22x_usb_power_supply_resources[] = {\n"
- ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, \"VBUS_REMOVAL\"),\n"
- ">> \302\240\302\240\302\240};\n"
+ ">> ?diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c\n"
+ ">> ?index cee5288..064e5015 100644\n"
+ ">> ?--- a/drivers/mfd/axp20x.c\n"
+ ">> ?+++ b/drivers/mfd/axp20x.c\n"
+ ">> ?@@ -166,6 +166,15 @@ static struct resource axp22x_usb_power_supply_resources[] = {\n"
+ ">> ???????????DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, \"VBUS_REMOVAL\"),\n"
+ ">> ???};\n"
  ">>\n"
- ">> \302\240+static struct resource axp22x_battery_resources[] = {\n"
- ">> \302\240+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_PLUGIN, \"BATT_PLUGIN\"),\n"
- ">> \302\240+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_REMOVAL, \"BATT_REMOVAL\"),\n"
- ">> \302\240+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_ENT_ACT_MODE, \"BATT_ENT_ACT_MODE\"),\n"
- ">> \302\240+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_EXIT_ACT_MODE, \"BATT_EXIT_ACT_MODE\"),\n"
- ">> \302\240+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG, \"CHARG\"),\n"
- ">> \302\240+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG_DONE, \"CHARG_DONE\"),\n"
- ">> \302\240+};\n"
- ">> \302\240+\n"
- ">> \302\240\302\240\302\240static struct resource axp22x_pek_resources[] = {\n"
- ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240{\n"
- ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240.name = \"PEK_DBR\",\n"
- ">> \302\240@@ -538,6 +547,11 @@ static struct mfd_cell axp22x_cells[] = {\n"
- ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240.of_compatible = \"x-powers,axp202-usb-power-supply\",\n"
- ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240.num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),\n"
- ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240.resources = axp22x_usb_power_supply_resources,\n"
- ">> \302\240+ }, {\n"
- ">> \302\240+ .name = \"axp20x-battery\",\n"
- ">> \302\240+ .of_compatible = \"x-powers,axp202-battery\",\n"
- ">> \302\240+ .num_resources = ARRAY_SIZE(axp22x_battery_resources),\n"
- ">> \302\240+ .resources = axp22x_battery_resources,\n"
- ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240},\n"
- ">> \302\240\302\240\302\240};\n"
+ ">> ?+static struct resource axp22x_battery_resources[] = {\n"
+ ">> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_PLUGIN, \"BATT_PLUGIN\"),\n"
+ ">> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_REMOVAL, \"BATT_REMOVAL\"),\n"
+ ">> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_ENT_ACT_MODE, \"BATT_ENT_ACT_MODE\"),\n"
+ ">> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_BATT_EXIT_ACT_MODE, \"BATT_EXIT_ACT_MODE\"),\n"
+ ">> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG, \"CHARG\"),\n"
+ ">> ?+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_CHARG_DONE, \"CHARG_DONE\"),\n"
+ ">> ?+};\n"
+ ">> ?+\n"
+ ">> ???static struct resource axp22x_pek_resources[] = {\n"
+ ">> ???????????{\n"
+ ">> ???????????????????.name = \"PEK_DBR\",\n"
+ ">> ?@@ -538,6 +547,11 @@ static struct mfd_cell axp22x_cells[] = {\n"
+ ">> ???????????????????.of_compatible = \"x-powers,axp202-usb-power-supply\",\n"
+ ">> ???????????????????.num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),\n"
+ ">> ???????????????????.resources = axp22x_usb_power_supply_resources,\n"
+ ">> ?+ }, {\n"
+ ">> ?+ .name = \"axp20x-battery\",\n"
+ ">> ?+ .of_compatible = \"x-powers,axp202-battery\",\n"
+ ">> ?+ .num_resources = ARRAY_SIZE(axp22x_battery_resources),\n"
+ ">> ?+ .resources = axp22x_battery_resources,\n"
+ ">> ???????????},\n"
+ ">> ???};\n"
  ">>\n"
- ">> \302\240diff --git a/drivers/power/Makefile b/drivers/power/Makefile\n"
- ">> \302\240index e46b75d..1452d23 100644\n"
- ">> \302\240--- a/drivers/power/Makefile\n"
- ">> \302\240+++ b/drivers/power/Makefile\n"
- ">> \302\240@@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o\n"
- ">> \302\240\302\240\302\240obj-$(CONFIG_PDA_POWER) += pda_power.o\n"
- ">> \302\240\302\240\302\240obj-$(CONFIG_APM_POWER) += apm_power.o\n"
- ">> \302\240\302\240\302\240obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o\n"
- ">> \302\240+obj-$(CONFIG_AXP20X_POWER) += axp20x_battery.o\n"
- ">> \302\240\302\240\302\240obj-$(CONFIG_MAX8925_POWER) += max8925_power.o\n"
- ">> \302\240\302\240\302\240obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o\n"
- ">> \302\240\302\240\302\240obj-$(CONFIG_WM831X_POWER) += wm831x_power.o\n"
- ">> \302\240diff --git a/drivers/power/axp20x_battery.c b/drivers/power/axp20x_battery.c\n"
- ">> \302\240new file mode 100644\n"
- ">> \302\240index 0000000..8fac2cd\n"
- ">> \302\240--- /dev/null\n"
- ">> \302\240+++ b/drivers/power/axp20x_battery.c\n"
- ">> \302\240@@ -0,0 +1,254 @@\n"
- ">> \302\240+/*\n"
- ">> \302\240+ * AXP20x PMIC battery status driver\n"
- ">> \302\240+ *\n"
- ">> \302\240+ * Copyright (C) 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>\n"
- ">> \302\240+ * Copyright (C) 2015 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>\n"
- ">> \302\240+ * Copyright (C) 2014 Bruno Pr\303\251mont <bonbons@linux-vserver.org>\n"
- ">> \302\240+ *\n"
- ">> \302\240+ * This program is free software; you can redistribute it and/or modify it\n"
- ">> \302\240+ * under the terms of the GNU General Public License as published by the\n"
- ">> \302\240+ * Free Software Foundation; either version 2 of the License, or (at your\n"
- ">> \302\240+ * option) any later version.\n"
- ">> \302\240+ */\n"
- ">> \302\240+\n"
- ">> \302\240+#include <linux/device.h>\n"
- ">> \302\240+#include <linux/init.h>\n"
- ">> \302\240+#include <linux/interrupt.h>\n"
- ">> \302\240+#include <linux/kernel.h>\n"
- ">> \302\240+#include <linux/mfd/axp20x.h>\n"
- ">> \302\240+#include <linux/module.h>\n"
- ">> \302\240+#include <linux/of.h>\n"
- ">> \302\240+#include <linux/platform_device.h>\n"
- ">> \302\240+#include <linux/power_supply.h>\n"
- ">> \302\240+#include <linux/regmap.h>\n"
- ">> \302\240+#include <linux/slab.h>\n"
- ">> \302\240+\n"
- ">> \302\240+#define DRVNAME \"axp20x-battery\"\n"
- ">> \302\240+\n"
- ">> \302\240+#define AXP20X_PWR_STATUS_ACIN_USED BIT(6)\n"
- ">> \302\240+#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)\n"
- ">> \302\240+#define AXP20X_PWR_STATUS_BAT_DIRECTION BIT(2)\n"
- ">> \302\240+\n"
- ">> \302\240+#define AXP20X_OP_MODE_CHARGING BIT(6)\n"
- ">> \302\240+#define AXP20X_OP_MODE_BATTERY_PRESENT BIT(5)\n"
- ">> \302\240+#define AXP20X_OP_MODE_BATTERY_ACTIVE BIT(3)\n"
- ">> \302\240+\n"
- ">> \302\240+#define AXP20X_CAPACITY_CORRECT BIT(7)\n"
- ">> \302\240+\n"
- ">> \302\240+struct axp20x_battery {\n"
- ">> \302\240+ struct axp20x_dev *axp20x;\n"
- ">> \302\240+ struct regmap *regmap;\n"
- ">> \302\240+ struct power_supply *supply;\n"
- ">> \302\240+};\n"
- ">> \302\240+\n"
- ">> \302\240+static irqreturn_t axp20x_battery_irq(int irq, void *devid)\n"
- ">> \302\240+{\n"
- ">> \302\240+ struct axp20x_battery *power = devid;\n"
- ">> \302\240+\n"
- ">> \302\240+ power_supply_changed(power->supply);\n"
- ">> \302\240+\n"
- ">> \302\240+ return IRQ_HANDLED;\n"
- ">> \302\240+}\n"
- ">> \302\240+\n"
- ">> \302\240+static int axp20x_battery_get_property(struct power_supply *psy,\n"
- ">> \302\240+ enum power_supply_property psp, union power_supply_propval *val)\n"
- ">> \302\240+{\n"
- ">> \302\240+ struct axp20x_battery *power = power_supply_get_drvdata(psy);\n"
- ">> \302\240+ unsigned int input, op_mode, capacity, dh, dl;\n"
- ">> \302\240+ int ret, ext;\n"
- ">> \302\240+\n"
- ">> \302\240+ /* All the properties below need the input-status reg value */\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_PWR_OP_MODE, &op_mode);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+\n"
- ">> \302\240+ switch (psp) {\n"
- ">> \302\240+ case POWER_SUPPLY_PROP_HEALTH:\n"
- ">> \302\240+ if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ }\n"
- ">> \302\240+\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_HEALTH_GOOD;\n"
- ">> \302\240+\n"
- ">> \302\240+ if (op_mode & AXP20X_OP_MODE_BATTERY_ACTIVE) {\n"
- ">> \302\240+ /* AXP20X is now trying to re-activate the battery */\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_HEALTH_DEAD;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ }\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ case POWER_SUPPLY_PROP_PRESENT:\n"
- ">> \302\240+ val->intval = !!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT);\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ case POWER_SUPPLY_PROP_CAPACITY:\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+ if (capacity & AXP20X_CAPACITY_CORRECT)\n"
- ">> \302\240+ val->intval = capacity & (~AXP20X_CAPACITY_CORRECT);\n"
- ">> \302\240+ else\n"
- ">> \302\240+ return -EIO;\n"
- ">> \302\240+ /* from axp_capchange function of Allwinner 3.4 driver */\n"
- ">> \302\240+ if (val->intval == 127)\n"
- ">> \302\240+ val->intval = 100;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ case POWER_SUPPLY_PROP_STATUS:\n"
- ">> \302\240+ if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ }\n"
- ">> \302\240+\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+\n"
- ">> \302\240+ ext = (input & AXP20X_PWR_STATUS_ACIN_USED) ||\n"
- ">> \302\240+ (input & AXP20X_PWR_STATUS_VBUS_USED);\n"
- ">> \302\240+\n"
- ">> \302\240+ if (op_mode & AXP20X_OP_MODE_CHARGING)\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_STATUS_CHARGING;\n"
- ">> \302\240+ else if (!(input & AXP20X_PWR_STATUS_BAT_DIRECTION) && !ext)\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;\n"
- ">> \302\240+ else if (capacity == (100 | AXP20X_CAPACITY_CORRECT) ||\n"
- ">> \302\240+ capacity == (127 | AXP20X_CAPACITY_CORRECT))\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_STATUS_FULL;\n"
- ">> \302\240+ else\n"
- ">> \302\240+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ case POWER_SUPPLY_PROP_CURRENT_NOW:\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_H, &dh);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_L, &dl);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+ /* it's a 12 bit integer, high 8-bit is stored in dh */\n"
- ">> \302\240+ val->intval = dh << 4 | dl >> 4;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_BATT_V_H, &dh);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+ ret = regmap_read(power->regmap, AXP20X_BATT_V_L, &dl);\n"
- ">> \302\240+ if (ret)\n"
- ">> \302\240+ return ret;\n"
- ">> \302\240+ /* it's a 12 bit integer, high 8-bit is stored in dh */\n"
- ">> \302\240+ val->intval = dh << 4 | dl >> 4;\n"
- ">> \302\240+ /* The formula below is from axp22_vbat_to_mV function\n"
- ">> \302\240+ * of Allwinner 3.4 kernel.\n"
- ">> \302\240+ */\n"
- ">> \302\240+ val->intval = val->intval * 1100 / 1000;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ default:\n"
- ">> \302\240+ return -EINVAL;\n"
- ">> \302\240+ }\n"
- ">> \302\240+\n"
- ">> \302\240+ return 0;\n"
- ">> \302\240+}\n"
- ">> \302\240+\n"
- ">> \302\240+static enum power_supply_property axp22x_battery_properties[] = {\n"
- ">> \302\240+ POWER_SUPPLY_PROP_CAPACITY,\n"
- ">> \302\240+ POWER_SUPPLY_PROP_HEALTH,\n"
- ">> \302\240+ POWER_SUPPLY_PROP_PRESENT,\n"
- ">> \302\240+ POWER_SUPPLY_PROP_STATUS,\n"
- ">> \302\240+ POWER_SUPPLY_PROP_CURRENT_NOW,\n"
- ">> \302\240+ POWER_SUPPLY_PROP_VOLTAGE_NOW,\n"
- ">> \302\240+};\n"
- ">> \302\240+\n"
- ">> \302\240+static const struct power_supply_desc axp22x_battery_desc = {\n"
- ">> \302\240+ .name = \"axp20x-battery\",\n"
- ">> \302\240+ .type = POWER_SUPPLY_TYPE_BATTERY,\n"
- ">> \302\240+ .properties = axp22x_battery_properties,\n"
- ">> \302\240+ .num_properties = ARRAY_SIZE(axp22x_battery_properties),\n"
- ">> \302\240+ .get_property = axp20x_battery_get_property,\n"
- ">> \302\240+};\n"
- ">> \302\240+\n"
- ">> \302\240+static int axp20x_battery_probe(struct platform_device *pdev)\n"
- ">> \302\240+{\n"
- ">> \302\240+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);\n"
- ">> \302\240+ struct power_supply_config psy_cfg = {};\n"
- ">> \302\240+ struct axp20x_battery *power;\n"
- ">> \302\240+ static const char * const axp22x_irq_names[] = {\n"
- ">> \302\240+ \"BATT_PLUGIN\", \"BATT_REMOVAL\", \"BATT_ENT_ACT_MODE\",\n"
- ">> \302\240+ \"BATT_EXIT_ACT_MODE\", \"CHARG\", \"CHARG_DONE\", NULL };\n"
- ">> \302\240+ static const char * const *irq_names;\n"
- ">> \302\240+ const struct power_supply_desc *battery_desc;\n"
- ">> \302\240+ int i, irq, ret;\n"
- ">> \302\240+\n"
- ">> \302\240+ if (!of_device_is_available(pdev->dev.of_node))\n"
- ">> \302\240+ return -ENODEV;\n"
- ">> \302\240+\n"
- ">> \302\240+ if (!axp20x) {\n"
- ">> \302\240+ dev_err(&pdev->dev, \"Parent drvdata not set\\n\");\n"
- ">> \302\240+ return -EINVAL;\n"
- ">> \302\240+ }\n"
- ">> \302\240+\n"
- ">> \302\240+ power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL);\n"
- ">> \302\240+ if (!power)\n"
- ">> \302\240+ return -ENOMEM;\n"
- ">> \302\240+\n"
- ">> \302\240+ power->axp20x = axp20x;\n"
- ">> \302\240+ power->regmap = axp20x->regmap;\n"
- ">> \302\240+\n"
- ">> \302\240+ switch (power->axp20x->variant) {\n"
- ">> \302\240+ case AXP221_ID:\n"
- ">> \302\240+ case AXP223_ID:\n"
- ">> \302\240+ battery_desc = &axp22x_battery_desc;\n"
- ">> \302\240+ irq_names = axp22x_irq_names;\n"
- ">> \302\240+ break;\n"
- ">> \302\240+ default:\n"
- ">> \302\240+ dev_err(&pdev->dev, \"Unsupported AXP variant: %ld\\n\",\n"
- ">> \302\240+ axp20x->variant);\n"
- ">> \302\240+ return -EINVAL;\n"
- ">> \302\240+ }\n"
- ">> \302\240+\n"
- ">> \302\240+ psy_cfg.of_node = pdev->dev.of_node;\n"
- ">> \302\240+ psy_cfg.drv_data = power;\n"
- ">> \302\240+\n"
- ">> \302\240+ power->supply = devm_power_supply_register(&pdev->dev, battery_desc,\n"
- ">> \302\240+ &psy_cfg);\n"
- ">> \302\240+ if (IS_ERR(power->supply))\n"
- ">> \302\240+ return PTR_ERR(power->supply);\n"
- ">> \302\240+\n"
- ">> \302\240+ /* Request irqs after registering, as irqs may trigger immediately */\n"
- ">> \302\240+ for (i = 0; irq_names[i]; i++) {\n"
- ">> \302\240+ irq = platform_get_irq_byname(pdev, irq_names[i]);\n"
- ">> \302\240+ if (irq < 0) {\n"
- ">> \302\240+ dev_warn(&pdev->dev, \"No IRQ for %s: %d\\n\",\n"
- ">> \302\240+ irq_names[i], irq);\n"
- ">> \302\240+ continue;\n"
- ">> \302\240+ }\n"
- ">> \302\240+ irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);\n"
- ">> \302\240+ ret = devm_request_any_context_irq(&pdev->dev, irq,\n"
- ">> \302\240+ axp20x_battery_irq, 0, DRVNAME, power);\n"
- ">> \302\240+ if (ret < 0)\n"
- ">> \302\240+ dev_warn(&pdev->dev, \"Error requesting %s IRQ: %d\\n\",\n"
- ">> \302\240+ irq_names[i], ret);\n"
- ">> \302\240+ }\n"
- ">> \302\240+\n"
- ">> \302\240+ return 0;\n"
- ">> \302\240+}\n"
- ">> \302\240+\n"
- ">> \302\240+static const struct of_device_id axp20x_battery_match[] = {\n"
- ">> \302\240+ { .compatible = \"x-powers,axp202-battery\" },\n"
- ">> \302\240+ { }\n"
- ">> \302\240+};\n"
- ">> \302\240+MODULE_DEVICE_TABLE(of, axp20x_battery_match);\n"
- ">> \302\240+\n"
- ">> \302\240+static struct platform_driver axp20x_battery_driver = {\n"
- ">> \302\240+ .probe = axp20x_battery_probe,\n"
- ">> \302\240+ .driver = {\n"
- ">> \302\240+ .name = DRVNAME,\n"
- ">> \302\240+ .of_match_table = axp20x_battery_match,\n"
- ">> \302\240+ },\n"
- ">> \302\240+};\n"
- ">> \302\240+\n"
- ">> \302\240+module_platform_driver(axp20x_battery_driver);\n"
- ">> \302\240+\n"
- ">> \302\240+MODULE_AUTHOR(\"Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>\");\n"
- ">> \302\240+MODULE_DESCRIPTION(\"AXP20x PMIC battery status driver\");\n"
- ">> \302\240+MODULE_LICENSE(\"GPL\");\n"
+ ">> ?diff --git a/drivers/power/Makefile b/drivers/power/Makefile\n"
+ ">> ?index e46b75d..1452d23 100644\n"
+ ">> ?--- a/drivers/power/Makefile\n"
+ ">> ?+++ b/drivers/power/Makefile\n"
+ ">> ?@@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o\n"
+ ">> ???obj-$(CONFIG_PDA_POWER) += pda_power.o\n"
+ ">> ???obj-$(CONFIG_APM_POWER) += apm_power.o\n"
+ ">> ???obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o\n"
+ ">> ?+obj-$(CONFIG_AXP20X_POWER) += axp20x_battery.o\n"
+ ">> ???obj-$(CONFIG_MAX8925_POWER) += max8925_power.o\n"
+ ">> ???obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o\n"
+ ">> ???obj-$(CONFIG_WM831X_POWER) += wm831x_power.o\n"
+ ">> ?diff --git a/drivers/power/axp20x_battery.c b/drivers/power/axp20x_battery.c\n"
+ ">> ?new file mode 100644\n"
+ ">> ?index 0000000..8fac2cd\n"
+ ">> ?--- /dev/null\n"
+ ">> ?+++ b/drivers/power/axp20x_battery.c\n"
+ ">> ?@@ -0,0 +1,254 @@\n"
+ ">> ?+/*\n"
+ ">> ?+ * AXP20x PMIC battery status driver\n"
+ ">> ?+ *\n"
+ ">> ?+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>\n"
+ ">> ?+ * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>\n"
+ ">> ?+ * Copyright (C) 2014 Bruno Pr?mont <bonbons@linux-vserver.org>\n"
+ ">> ?+ *\n"
+ ">> ?+ * This program is free software; you can redistribute it and/or modify it\n"
+ ">> ?+ * under the terms of the GNU General Public License as published by the\n"
+ ">> ?+ * Free Software Foundation; either version 2 of the License, or (at your\n"
+ ">> ?+ * option) any later version.\n"
+ ">> ?+ */\n"
+ ">> ?+\n"
+ ">> ?+#include <linux/device.h>\n"
+ ">> ?+#include <linux/init.h>\n"
+ ">> ?+#include <linux/interrupt.h>\n"
+ ">> ?+#include <linux/kernel.h>\n"
+ ">> ?+#include <linux/mfd/axp20x.h>\n"
+ ">> ?+#include <linux/module.h>\n"
+ ">> ?+#include <linux/of.h>\n"
+ ">> ?+#include <linux/platform_device.h>\n"
+ ">> ?+#include <linux/power_supply.h>\n"
+ ">> ?+#include <linux/regmap.h>\n"
+ ">> ?+#include <linux/slab.h>\n"
+ ">> ?+\n"
+ ">> ?+#define DRVNAME \"axp20x-battery\"\n"
+ ">> ?+\n"
+ ">> ?+#define AXP20X_PWR_STATUS_ACIN_USED BIT(6)\n"
+ ">> ?+#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)\n"
+ ">> ?+#define AXP20X_PWR_STATUS_BAT_DIRECTION BIT(2)\n"
+ ">> ?+\n"
+ ">> ?+#define AXP20X_OP_MODE_CHARGING BIT(6)\n"
+ ">> ?+#define AXP20X_OP_MODE_BATTERY_PRESENT BIT(5)\n"
+ ">> ?+#define AXP20X_OP_MODE_BATTERY_ACTIVE BIT(3)\n"
+ ">> ?+\n"
+ ">> ?+#define AXP20X_CAPACITY_CORRECT BIT(7)\n"
+ ">> ?+\n"
+ ">> ?+struct axp20x_battery {\n"
+ ">> ?+ struct axp20x_dev *axp20x;\n"
+ ">> ?+ struct regmap *regmap;\n"
+ ">> ?+ struct power_supply *supply;\n"
+ ">> ?+};\n"
+ ">> ?+\n"
+ ">> ?+static irqreturn_t axp20x_battery_irq(int irq, void *devid)\n"
+ ">> ?+{\n"
+ ">> ?+ struct axp20x_battery *power = devid;\n"
+ ">> ?+\n"
+ ">> ?+ power_supply_changed(power->supply);\n"
+ ">> ?+\n"
+ ">> ?+ return IRQ_HANDLED;\n"
+ ">> ?+}\n"
+ ">> ?+\n"
+ ">> ?+static int axp20x_battery_get_property(struct power_supply *psy,\n"
+ ">> ?+ enum power_supply_property psp, union power_supply_propval *val)\n"
+ ">> ?+{\n"
+ ">> ?+ struct axp20x_battery *power = power_supply_get_drvdata(psy);\n"
+ ">> ?+ unsigned int input, op_mode, capacity, dh, dl;\n"
+ ">> ?+ int ret, ext;\n"
+ ">> ?+\n"
+ ">> ?+ /* All the properties below need the input-status reg value */\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_PWR_OP_MODE, &op_mode);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+\n"
+ ">> ?+ switch (psp) {\n"
+ ">> ?+ case POWER_SUPPLY_PROP_HEALTH:\n"
+ ">> ?+ if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {\n"
+ ">> ?+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;\n"
+ ">> ?+ break;\n"
+ ">> ?+ }\n"
+ ">> ?+\n"
+ ">> ?+ val->intval = POWER_SUPPLY_HEALTH_GOOD;\n"
+ ">> ?+\n"
+ ">> ?+ if (op_mode & AXP20X_OP_MODE_BATTERY_ACTIVE) {\n"
+ ">> ?+ /* AXP20X is now trying to re-activate the battery */\n"
+ ">> ?+ val->intval = POWER_SUPPLY_HEALTH_DEAD;\n"
+ ">> ?+ break;\n"
+ ">> ?+ }\n"
+ ">> ?+ break;\n"
+ ">> ?+ case POWER_SUPPLY_PROP_PRESENT:\n"
+ ">> ?+ val->intval = !!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT);\n"
+ ">> ?+ break;\n"
+ ">> ?+ case POWER_SUPPLY_PROP_CAPACITY:\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+ if (capacity & AXP20X_CAPACITY_CORRECT)\n"
+ ">> ?+ val->intval = capacity & (~AXP20X_CAPACITY_CORRECT);\n"
+ ">> ?+ else\n"
+ ">> ?+ return -EIO;\n"
+ ">> ?+ /* from axp_capchange function of Allwinner 3.4 driver */\n"
+ ">> ?+ if (val->intval == 127)\n"
+ ">> ?+ val->intval = 100;\n"
+ ">> ?+ break;\n"
+ ">> ?+ case POWER_SUPPLY_PROP_STATUS:\n"
+ ">> ?+ if (!(op_mode & AXP20X_OP_MODE_BATTERY_PRESENT)) {\n"
+ ">> ?+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;\n"
+ ">> ?+ break;\n"
+ ">> ?+ }\n"
+ ">> ?+\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_FG_RES, &capacity);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+\n"
+ ">> ?+ ext = (input & AXP20X_PWR_STATUS_ACIN_USED) ||\n"
+ ">> ?+ (input & AXP20X_PWR_STATUS_VBUS_USED);\n"
+ ">> ?+\n"
+ ">> ?+ if (op_mode & AXP20X_OP_MODE_CHARGING)\n"
+ ">> ?+ val->intval = POWER_SUPPLY_STATUS_CHARGING;\n"
+ ">> ?+ else if (!(input & AXP20X_PWR_STATUS_BAT_DIRECTION) && !ext)\n"
+ ">> ?+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;\n"
+ ">> ?+ else if (capacity == (100 | AXP20X_CAPACITY_CORRECT) ||\n"
+ ">> ?+ capacity == (127 | AXP20X_CAPACITY_CORRECT))\n"
+ ">> ?+ val->intval = POWER_SUPPLY_STATUS_FULL;\n"
+ ">> ?+ else\n"
+ ">> ?+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;\n"
+ ">> ?+ break;\n"
+ ">> ?+ case POWER_SUPPLY_PROP_CURRENT_NOW:\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_H, &dh);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_DISCHRG_I_L, &dl);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+ /* it's a 12 bit integer, high 8-bit is stored in dh */\n"
+ ">> ?+ val->intval = dh << 4 | dl >> 4;\n"
+ ">> ?+ break;\n"
+ ">> ?+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_V_H, &dh);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+ ret = regmap_read(power->regmap, AXP20X_BATT_V_L, &dl);\n"
+ ">> ?+ if (ret)\n"
+ ">> ?+ return ret;\n"
+ ">> ?+ /* it's a 12 bit integer, high 8-bit is stored in dh */\n"
+ ">> ?+ val->intval = dh << 4 | dl >> 4;\n"
+ ">> ?+ /* The formula below is from axp22_vbat_to_mV function\n"
+ ">> ?+ * of Allwinner 3.4 kernel.\n"
+ ">> ?+ */\n"
+ ">> ?+ val->intval = val->intval * 1100 / 1000;\n"
+ ">> ?+ break;\n"
+ ">> ?+ default:\n"
+ ">> ?+ return -EINVAL;\n"
+ ">> ?+ }\n"
+ ">> ?+\n"
+ ">> ?+ return 0;\n"
+ ">> ?+}\n"
+ ">> ?+\n"
+ ">> ?+static enum power_supply_property axp22x_battery_properties[] = {\n"
+ ">> ?+ POWER_SUPPLY_PROP_CAPACITY,\n"
+ ">> ?+ POWER_SUPPLY_PROP_HEALTH,\n"
+ ">> ?+ POWER_SUPPLY_PROP_PRESENT,\n"
+ ">> ?+ POWER_SUPPLY_PROP_STATUS,\n"
+ ">> ?+ POWER_SUPPLY_PROP_CURRENT_NOW,\n"
+ ">> ?+ POWER_SUPPLY_PROP_VOLTAGE_NOW,\n"
+ ">> ?+};\n"
+ ">> ?+\n"
+ ">> ?+static const struct power_supply_desc axp22x_battery_desc = {\n"
+ ">> ?+ .name = \"axp20x-battery\",\n"
+ ">> ?+ .type = POWER_SUPPLY_TYPE_BATTERY,\n"
+ ">> ?+ .properties = axp22x_battery_properties,\n"
+ ">> ?+ .num_properties = ARRAY_SIZE(axp22x_battery_properties),\n"
+ ">> ?+ .get_property = axp20x_battery_get_property,\n"
+ ">> ?+};\n"
+ ">> ?+\n"
+ ">> ?+static int axp20x_battery_probe(struct platform_device *pdev)\n"
+ ">> ?+{\n"
+ ">> ?+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);\n"
+ ">> ?+ struct power_supply_config psy_cfg = {};\n"
+ ">> ?+ struct axp20x_battery *power;\n"
+ ">> ?+ static const char * const axp22x_irq_names[] = {\n"
+ ">> ?+ \"BATT_PLUGIN\", \"BATT_REMOVAL\", \"BATT_ENT_ACT_MODE\",\n"
+ ">> ?+ \"BATT_EXIT_ACT_MODE\", \"CHARG\", \"CHARG_DONE\", NULL };\n"
+ ">> ?+ static const char * const *irq_names;\n"
+ ">> ?+ const struct power_supply_desc *battery_desc;\n"
+ ">> ?+ int i, irq, ret;\n"
+ ">> ?+\n"
+ ">> ?+ if (!of_device_is_available(pdev->dev.of_node))\n"
+ ">> ?+ return -ENODEV;\n"
+ ">> ?+\n"
+ ">> ?+ if (!axp20x) {\n"
+ ">> ?+ dev_err(&pdev->dev, \"Parent drvdata not set\\n\");\n"
+ ">> ?+ return -EINVAL;\n"
+ ">> ?+ }\n"
+ ">> ?+\n"
+ ">> ?+ power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL);\n"
+ ">> ?+ if (!power)\n"
+ ">> ?+ return -ENOMEM;\n"
+ ">> ?+\n"
+ ">> ?+ power->axp20x = axp20x;\n"
+ ">> ?+ power->regmap = axp20x->regmap;\n"
+ ">> ?+\n"
+ ">> ?+ switch (power->axp20x->variant) {\n"
+ ">> ?+ case AXP221_ID:\n"
+ ">> ?+ case AXP223_ID:\n"
+ ">> ?+ battery_desc = &axp22x_battery_desc;\n"
+ ">> ?+ irq_names = axp22x_irq_names;\n"
+ ">> ?+ break;\n"
+ ">> ?+ default:\n"
+ ">> ?+ dev_err(&pdev->dev, \"Unsupported AXP variant: %ld\\n\",\n"
+ ">> ?+ axp20x->variant);\n"
+ ">> ?+ return -EINVAL;\n"
+ ">> ?+ }\n"
+ ">> ?+\n"
+ ">> ?+ psy_cfg.of_node = pdev->dev.of_node;\n"
+ ">> ?+ psy_cfg.drv_data = power;\n"
+ ">> ?+\n"
+ ">> ?+ power->supply = devm_power_supply_register(&pdev->dev, battery_desc,\n"
+ ">> ?+ &psy_cfg);\n"
+ ">> ?+ if (IS_ERR(power->supply))\n"
+ ">> ?+ return PTR_ERR(power->supply);\n"
+ ">> ?+\n"
+ ">> ?+ /* Request irqs after registering, as irqs may trigger immediately */\n"
+ ">> ?+ for (i = 0; irq_names[i]; i++) {\n"
+ ">> ?+ irq = platform_get_irq_byname(pdev, irq_names[i]);\n"
+ ">> ?+ if (irq < 0) {\n"
+ ">> ?+ dev_warn(&pdev->dev, \"No IRQ for %s: %d\\n\",\n"
+ ">> ?+ irq_names[i], irq);\n"
+ ">> ?+ continue;\n"
+ ">> ?+ }\n"
+ ">> ?+ irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);\n"
+ ">> ?+ ret = devm_request_any_context_irq(&pdev->dev, irq,\n"
+ ">> ?+ axp20x_battery_irq, 0, DRVNAME, power);\n"
+ ">> ?+ if (ret < 0)\n"
+ ">> ?+ dev_warn(&pdev->dev, \"Error requesting %s IRQ: %d\\n\",\n"
+ ">> ?+ irq_names[i], ret);\n"
+ ">> ?+ }\n"
+ ">> ?+\n"
+ ">> ?+ return 0;\n"
+ ">> ?+}\n"
+ ">> ?+\n"
+ ">> ?+static const struct of_device_id axp20x_battery_match[] = {\n"
+ ">> ?+ { .compatible = \"x-powers,axp202-battery\" },\n"
+ ">> ?+ { }\n"
+ ">> ?+};\n"
+ ">> ?+MODULE_DEVICE_TABLE(of, axp20x_battery_match);\n"
+ ">> ?+\n"
+ ">> ?+static struct platform_driver axp20x_battery_driver = {\n"
+ ">> ?+ .probe = axp20x_battery_probe,\n"
+ ">> ?+ .driver = {\n"
+ ">> ?+ .name = DRVNAME,\n"
+ ">> ?+ .of_match_table = axp20x_battery_match,\n"
+ ">> ?+ },\n"
+ ">> ?+};\n"
+ ">> ?+\n"
+ ">> ?+module_platform_driver(axp20x_battery_driver);\n"
+ ">> ?+\n"
+ ">> ?+MODULE_AUTHOR(\"Icenowy Zheng <icenowy@aosc.xyz>\");\n"
+ ">> ?+MODULE_DESCRIPTION(\"AXP20x PMIC battery status driver\");\n"
+ ">> ?+MODULE_LICENSE(\"GPL\");\n"
  "\n"
  "Therotically, it can run on axp20x. However, I have currently no test device. (Still waiting for my C.H.I.P.)\n"
- "So I can only promise it to run on axp22x.\n"
- "\n"
- "-- \n"
- "You received this message because you are subscribed to the Google Groups \"linux-sunxi\" group.\n"
- "To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org\n"
- For more options, visit https://groups.google.com/d/optout.
+ So I can only promise it to run on axp22x.
 
-16784d3c662af5c1bdde2c12eab440e5e9a497e62ae95336ec61c036ef315c29
+9fb2491c8839e115b80f62341560dd6043a29e7952b0e97b17c5bec1730d667b

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.