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.