All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] mfd: axp20x: add adc volatile ranges for axp22x
@ 2016-07-01  9:29 ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: wens-jdAy2FN1RRM, maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

AXP22x has also some different register map than axp20x, they're also
added here.

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
 drivers/mfd/axp20x.c       | 1 +
 include/linux/mfd/axp20x.h | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index d62209d..cee5288 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -96,6 +96,7 @@ static const struct regmap_range axp22x_volatile_ranges[] = {
 	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
 	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
 	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
 };
 
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index 0be4982..ad3d9c7 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -201,6 +201,10 @@ enum {
 #define AXP20X_OCV_MAX			0xf
 
 /* AXP22X specific registers */
+#define AXP22X_PMIC_ADC_H		0x56
+#define AXP22X_PMIC_ADC_L		0x57
+#define AXP22X_TS_ADC_H			0x58
+#define AXP22X_TS_ADC_L			0x59
 #define AXP22X_BATLOW_THRES1		0xe6
 
 /* AXP288 specific registers */
-- 
2.9.0

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

* [PATCH 1/4] mfd: axp20x: add adc volatile ranges for axp22x
@ 2016-07-01  9:29 ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: linux-arm-kernel

AXP22x has also some different register map than axp20x, they're also
added here.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 drivers/mfd/axp20x.c       | 1 +
 include/linux/mfd/axp20x.h | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index d62209d..cee5288 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -96,6 +96,7 @@ static const struct regmap_range axp22x_volatile_ranges[] = {
 	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
 	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
 	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
 };
 
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index 0be4982..ad3d9c7 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -201,6 +201,10 @@ enum {
 #define AXP20X_OCV_MAX			0xf
 
 /* AXP22X specific registers */
+#define AXP22X_PMIC_ADC_H		0x56
+#define AXP22X_PMIC_ADC_L		0x57
+#define AXP22X_TS_ADC_H			0x58
+#define AXP22X_TS_ADC_L			0x59
 #define AXP22X_BATLOW_THRES1		0xe6
 
 /* AXP288 specific registers */
-- 
2.9.0

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

* [PATCH 2/4] power: add axp20x-battery driver
  2016-07-01  9:29 ` Icenowy Zheng
@ 2016-07-01  9:29     ` Icenowy Zheng
  -1 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: wens-jdAy2FN1RRM, maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

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

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,
 	},
 };
 
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-ud5FBsm0p/xEiooADzr8i9i2O/JbrIOy@public.gmane.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");
-- 
2.9.0

-- 
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.

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

* [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-01  9:29     ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: linux-arm-kernel

This driver is the battery power supply driver of axp20x PMIC. Currently
it supports only AXP22x variants.

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"),
 };
 
+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@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");
-- 
2.9.0

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

* [PATCH 3/4] ARM: sun8i: add axp20x-battery node for axp22x
  2016-07-01  9:29 ` Icenowy Zheng
@ 2016-07-01  9:29     ` Icenowy Zheng
  -1 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: wens-jdAy2FN1RRM, maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
 arch/arm/boot/dts/axp22x.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/axp22x.dtsi b/arch/arm/boot/dts/axp22x.dtsi
index f05cbf6..4abcac5 100644
--- a/arch/arm/boot/dts/axp22x.dtsi
+++ b/arch/arm/boot/dts/axp22x.dtsi
@@ -150,4 +150,9 @@
 		compatible = "x-powers,axp202-usb-power-supply";
 		status = "disabled";
 	};
+
+	battery: battery {
+		compatible = "x-powers,axp202-battery";
+		status = "disabled";
+	};
 };
-- 
2.9.0

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

* [PATCH 3/4] ARM: sun8i: add axp20x-battery node for axp22x
@ 2016-07-01  9:29     ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/axp22x.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/axp22x.dtsi b/arch/arm/boot/dts/axp22x.dtsi
index f05cbf6..4abcac5 100644
--- a/arch/arm/boot/dts/axp22x.dtsi
+++ b/arch/arm/boot/dts/axp22x.dtsi
@@ -150,4 +150,9 @@
 		compatible = "x-powers,axp202-usb-power-supply";
 		status = "disabled";
 	};
+
+	battery: battery {
+		compatible = "x-powers,axp202-battery";
+		status = "disabled";
+	};
 };
-- 
2.9.0

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

* [PATCH 4/4] ARM: sun8i: enable axp22x-battery on A23/33 Q8 tablets
  2016-07-01  9:29 ` Icenowy Zheng
@ 2016-07-01  9:29     ` Icenowy Zheng
  -1 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: wens-jdAy2FN1RRM, maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
 arch/arm/boot/dts/sun8i-q8-common.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-q8-common.dtsi b/arch/arm/boot/dts/sun8i-q8-common.dtsi
index 2e2cbf5..42beec9 100644
--- a/arch/arm/boot/dts/sun8i-q8-common.dtsi
+++ b/arch/arm/boot/dts/sun8i-q8-common.dtsi
@@ -199,6 +199,10 @@
 	status = "okay";
 };
 
+&battery {
+	status = "okay";
+};
+
 &usbphy {
 	pinctrl-names = "default";
 	pinctrl-0 = <&usb0_id_detect_pin>;
-- 
2.9.0

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

* [PATCH 4/4] ARM: sun8i: enable axp22x-battery on A23/33 Q8 tablets
@ 2016-07-01  9:29     ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-01  9:29 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-q8-common.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-q8-common.dtsi b/arch/arm/boot/dts/sun8i-q8-common.dtsi
index 2e2cbf5..42beec9 100644
--- a/arch/arm/boot/dts/sun8i-q8-common.dtsi
+++ b/arch/arm/boot/dts/sun8i-q8-common.dtsi
@@ -199,6 +199,10 @@
 	status = "okay";
 };
 
+&battery {
+	status = "okay";
+};
+
 &usbphy {
 	pinctrl-names = "default";
 	pinctrl-0 = <&usb0_id_detect_pin>;
-- 
2.9.0

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

* Re: [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  5:26       ` Michael Haas
  0 siblings, 0 replies; 34+ messages in thread
From: Michael Haas @ 2016-07-05  5:26 UTC (permalink / raw)
  To: icenowy, wens, maxime.ripard, sre, dbaryshkov, dwmw2
  Cc: robh+dt, mark.rutland, linux, devicetree, linux-arm-kernel,
	linux-kernel, linux-pm, linux-sunxi

Hi,

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 
ready for submission. Do you know what pieces are missing in your driver 
for axp20x support - as opposed to axp22x, which is already working?

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.
>
> 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"),
>   };
>   
> +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@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");

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  5:26       ` Michael Haas
  0 siblings, 0 replies; 34+ messages in thread
From: Michael Haas @ 2016-07-05  5:26 UTC (permalink / raw)
  To: icenowy-ymACFijhrKM, wens-jdAy2FN1RRM,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

Hi,

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 
ready for submission. Do you know what pieces are missing in your driver 
for axp20x support - as opposed to axp22x, which is already working?

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.
>
> 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
>
> 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,
>   	},
>   };
>   
> 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-ud5FBsm0p/xEiooADzr8i9i2O/JbrIOy@public.gmane.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");

-- 
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.

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  5:26       ` Michael Haas
  0 siblings, 0 replies; 34+ messages in thread
From: Michael Haas @ 2016-07-05  5:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

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 
ready for submission. Do you know what pieces are missing in your driver 
for axp20x support - as opposed to axp22x, which is already working?

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.
>
> 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"),
>   };
>   
> +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@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");

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
  2016-07-05  5:26       ` Michael Haas
@ 2016-07-05  8:33           ` Icenowy Zheng
  -1 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-05  8:33 UTC (permalink / raw)
  To: Michael Haas, wens-jdAy2FN1RRM,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw



05.07.2016, 13:26, "Michael Haas" <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>:
> Hi,
>
> 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
> ready for submission. Do you know what pieces are missing in your driver
> for axp20x support - as opposed to axp22x, which is already working?
>
> 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.
>>
>>  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
>>
>>  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,
>>            },
>>    };
>>
>>  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");

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.

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  8:33           ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-05  8:33 UTC (permalink / raw)
  To: linux-arm-kernel



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
> axp20x?
>
> I've got a reworked version of that lying around, but it's not quite
> ready for submission. Do you know what pieces are missing in your driver
> for axp20x support - as opposed to axp22x, which is already working?
>
> 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.
>>
>> ?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"),
>> ???};
>>
>> ?+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@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.

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
  2016-07-05  5:26       ` Michael Haas
@ 2016-07-05  8:47           ` Icenowy Zheng
  -1 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-05  8:47 UTC (permalink / raw)
  To: Michael Haas, wens-jdAy2FN1RRM,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw



05.07.2016, 13:26, "Michael Haas" <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>:
> Hi,
>
> 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
> ready for submission. Do you know what pieces are missing in your driver
> for axp20x support - as opposed to axp22x, which is already working?
>
> 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.
>>
>>  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
>>
>>  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,
>>            },
>>    };
>>
>>  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");

I read the datasheet of axp20x, and then found that this driver does not support backup RTC battery. 
(But maybe backup battery do not need a driver -- at least on IBM PC it has no driver)

And I don't know whether the axp20x has default Li-ion/LiPo battery OCV parameter. (axp22x seems to be have a set of default OCV)

You can test this driver on AXP20x. (I think I didn't access to AXP22x-specified registers in the power supply code)

-- 
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.

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  8:47           ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-05  8:47 UTC (permalink / raw)
  To: linux-arm-kernel



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
> axp20x?
>
> I've got a reworked version of that lying around, but it's not quite
> ready for submission. Do you know what pieces are missing in your driver
> for axp20x support - as opposed to axp22x, which is already working?
>
> 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.
>>
>> ?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"),
>> ???};
>>
>> ?+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@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");

I read the datasheet of axp20x, and then found that this driver does not support backup RTC battery. 
(But maybe backup battery do not need a driver -- at least on IBM PC it has no driver)

And I don't know whether the axp20x has default Li-ion/LiPo battery OCV parameter. (axp22x seems to be have a set of default OCV)

You can test this driver on AXP20x. (I think I didn't access to AXP22x-specified registers in the power supply code)

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

* Re: [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  9:25             ` maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
  0 siblings, 0 replies; 34+ messages in thread
From: maxime.ripard @ 2016-07-05  9:25 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Michael Haas, wens, sre, dbaryshkov, dwmw2, robh+dt,
	mark.rutland, linux, devicetree, linux-arm-kernel, linux-kernel,
	linux-pm, linux-sunxi

[-- Attachment #1: Type: text/plain, Size: 1178 bytes --]

On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
> 
> 
> 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
> > axp20x?
> >
> > I've got a reworked version of that lying around, but it's not quite
> > ready for submission. Do you know what pieces are missing in your driver
> > for axp20x support - as opposed to axp22x, which is already working?
> 
> 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.

Still, it looks like you just took Bruno's driver, stripped out the
axp20x parts and added the one to deal with axp22x.

This makes the driver look weird, by being called axp20x, without
actually supporting those PMICs, but having some axp22x variables
right in the middle. And that's awfully inconsistent.

I'd rather have you add the AXP20x driver directly, and then add the
needed stuff for the AXP22x.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  9:25             ` maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
  0 siblings, 0 replies; 34+ messages in thread
From: maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8 @ 2016-07-05  9:25 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Michael Haas, wens-jdAy2FN1RRM, sre-DgEjT+Ai2ygdnm+yROfE0A,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

[-- Attachment #1: Type: text/plain, Size: 1529 bytes --]

On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
> 
> 
> 05.07.2016, 13:26, "Michael Haas" <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>:
> > Hi,
> >
> > 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
> > ready for submission. Do you know what pieces are missing in your driver
> > for axp20x support - as opposed to axp22x, which is already working?
> 
> 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.

Still, it looks like you just took Bruno's driver, stripped out the
axp20x parts and added the one to deal with axp22x.

This makes the driver look weird, by being called axp20x, without
actually supporting those PMICs, but having some axp22x variables
right in the middle. And that's awfully inconsistent.

I'd rather have you add the AXP20x driver directly, and then add the
needed stuff for the AXP22x.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

-- 
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.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05  9:25             ` maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
  0 siblings, 0 replies; 34+ messages in thread
From: maxime.ripard at free-electrons.com @ 2016-07-05  9:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
> 
> 
> 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
> > axp20x?
> >
> > I've got a reworked version of that lying around, but it's not quite
> > ready for submission. Do you know what pieces are missing in your driver
> > for axp20x support - as opposed to axp22x, which is already working?
> 
> 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.

Still, it looks like you just took Bruno's driver, stripped out the
axp20x parts and added the one to deal with axp22x.

This makes the driver look weird, by being called axp20x, without
actually supporting those PMICs, but having some axp22x variables
right in the middle. And that's awfully inconsistent.

I'd rather have you add the AXP20x driver directly, and then add the
needed stuff for the AXP22x.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160705/5afd99f8/attachment.sig>

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
  2016-07-05  9:25             ` maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
@ 2016-07-05 10:09               ` Icenowy Zheng
  -1 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-05 10:09 UTC (permalink / raw)
  To: maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
  Cc: Michael Haas, wens-jdAy2FN1RRM, sre-DgEjT+Ai2ygdnm+yROfE0A,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw



05.07.2016, 17:25, "maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org" <maxime.ripard@free-electrons.com>:
> On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
>>  05.07.2016, 13:26, "Michael Haas" <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>:
>>  > Hi,
>>  >
>>  > 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
>>  > ready for submission. Do you know what pieces are missing in your driver
>>  > for axp20x support - as opposed to axp22x, which is already working?
>>
>>  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.
>
> Still, it looks like you just took Bruno's driver, stripped out the
> axp20x parts and added the one to deal with axp22x.
>
> This makes the driver look weird, by being called axp20x, without
> actually supporting those PMICs, but having some axp22x variables
> right in the middle. And that's awfully inconsistent.
>
> I'd rather have you add the AXP20x driver directly, and then add the
> needed stuff for the AXP22x.
>
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

I modified axp20x_usb_power.c to suite the battery.

No axp22x-specified register is used in this driver.
I think this driver may now also work properly on axp20x, however
I have currently no device with axp20x.
(I didn't enter linux-sunxi when A10/13/20 is popular... So I'm waiting for
my CHIP)

This driver didn't implement OCV value tweak.

In fact, OCV value tweaking is even not documented in the datasheet
of both axp20x and axp22x.

Can you test it with axp20x? (It seems that the shipment of CHIP is so slow)

-- 
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.

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05 10:09               ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-05 10:09 UTC (permalink / raw)
  To: linux-arm-kernel



05.07.2016, 17:25, "maxime.ripard at free-electrons.com" <maxime.ripard@free-electrons.com>:
> On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
>> ?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
>> ?> axp20x?
>> ?>
>> ?> I've got a reworked version of that lying around, but it's not quite
>> ?> ready for submission. Do you know what pieces are missing in your driver
>> ?> for axp20x support - as opposed to axp22x, which is already working?
>>
>> ?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.
>
> Still, it looks like you just took Bruno's driver, stripped out the
> axp20x parts and added the one to deal with axp22x.
>
> This makes the driver look weird, by being called axp20x, without
> actually supporting those PMICs, but having some axp22x variables
> right in the middle. And that's awfully inconsistent.
>
> I'd rather have you add the AXP20x driver directly, and then add the
> needed stuff for the AXP22x.
>
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

I modified axp20x_usb_power.c to suite the battery.

No axp22x-specified register is used in this driver.
I think this driver may now also work properly on axp20x, however
I have currently no device with axp20x.
(I didn't enter linux-sunxi when A10/13/20 is popular... So I'm waiting for
my CHIP)

This driver didn't implement OCV value tweak.

In fact, OCV value tweaking is even not documented in the datasheet
of both axp20x and axp22x.

Can you test it with axp20x? (It seems that the shipment of CHIP is so slow)

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

* Re: [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05 12:43             ` Bruno Prémont
  0 siblings, 0 replies; 34+ messages in thread
From: Bruno Prémont @ 2016-07-05 12:43 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Michael Haas, Wens, Maxime Ripard, sre, dbaryshkov, dwmw2,
	robh+dt, Mark Rutland, linux, devicetree, linux-arm-kernel,
	linux-kernel, linux-pm, linux-sunxi

On Tue, 05 Jul 2016 16:47:38 +0800 Icenowy Zheng wrote:
> I read the datasheet of axp20x, and then found that this driver does
> not support backup RTC battery.
> (But maybe backup battery do not need a driver -- at least on IBM PC
> it has no driver)

A driver is needed to enable/disable the RTC battery charging (unless
uboot does it).
However all the driver can do according to datasheet is configure the
charge voltage/current or disable charging completely.
Monitoring RTC battery is not possible, neither is presence detection.

So driver should just apply configuration it finds in device-tree and
eventually share that information via power supply class.

> And I don't know whether the axp20x has default Li-ion/LiPo battery
> OCV parameter. (axp22x seems to be have a set of default OCV)

It seems to have default OCV parameters as well. With empty RTC
battery OCV values are present.

> You can test this driver on AXP20x. (I think I didn't access to
> AXP22x-specified registers in the power supply code)

Bruno

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05 12:43             ` Bruno Prémont
  0 siblings, 0 replies; 34+ messages in thread
From: Bruno Prémont @ 2016-07-05 12:43 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Michael Haas, Wens, Maxime Ripard, sre-DgEjT+Ai2ygdnm+yROfE0A,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Mark Rutland,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

On Tue, 05 Jul 2016 16:47:38 +0800 Icenowy Zheng wrote:
> I read the datasheet of axp20x, and then found that this driver does
> not support backup RTC battery.
> (But maybe backup battery do not need a driver -- at least on IBM PC
> it has no driver)

A driver is needed to enable/disable the RTC battery charging (unless
uboot does it).
However all the driver can do according to datasheet is configure the
charge voltage/current or disable charging completely.
Monitoring RTC battery is not possible, neither is presence detection.

So driver should just apply configuration it finds in device-tree and
eventually share that information via power supply class.

> And I don't know whether the axp20x has default Li-ion/LiPo battery
> OCV parameter. (axp22x seems to be have a set of default OCV)

It seems to have default OCV parameters as well. With empty RTC
battery OCV values are present.

> You can test this driver on AXP20x. (I think I didn't access to
> AXP22x-specified registers in the power supply code)

Bruno

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05 12:43             ` Bruno Prémont
  0 siblings, 0 replies; 34+ messages in thread
From: Bruno Prémont @ 2016-07-05 12:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 05 Jul 2016 16:47:38 +0800 Icenowy Zheng wrote:
> I read the datasheet of axp20x, and then found that this driver does
> not support backup RTC battery.
> (But maybe backup battery do not need a driver -- at least on IBM PC
> it has no driver)

A driver is needed to enable/disable the RTC battery charging (unless
uboot does it).
However all the driver can do according to datasheet is configure the
charge voltage/current or disable charging completely.
Monitoring RTC battery is not possible, neither is presence detection.

So driver should just apply configuration it finds in device-tree and
eventually share that information via power supply class.

> And I don't know whether the axp20x has default Li-ion/LiPo battery
> OCV parameter. (axp22x seems to be have a set of default OCV)

It seems to have default OCV parameters as well. With empty RTC
battery OCV values are present.

> You can test this driver on AXP20x. (I think I didn't access to
> AXP22x-specified registers in the power supply code)

Bruno

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

* Re: [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
  2016-07-05  9:25             ` maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
  (?)
@ 2016-07-05 12:45               ` Bruno Prémont
  -1 siblings, 0 replies; 34+ messages in thread
From: Bruno Prémont @ 2016-07-05 12:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Icenowy Zheng, Michael Haas, wens, sre, dbaryshkov, dwmw2,
	robh+dt, Mark Rutland, linux, devicetree, linux-arm-kernel,
	linux-kernel, linux-pm, linux-sunxi

On Tue, 5 Jul 2016 11:25:10 +0200 Maxime Ripard wrote:
> On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
> > 
> > 
> > 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
> > > axp20x?
> > >
> > > I've got a reworked version of that lying around, but it's not quite
> > > ready for submission. Do you know what pieces are missing in your driver
> > > for axp20x support - as opposed to axp22x, which is already working?  
> > 
> > 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.  
> 
> Still, it looks like you just took Bruno's driver, stripped out the
> axp20x parts and added the one to deal with axp22x.
> 
> This makes the driver look weird, by being called axp20x, without
> actually supporting those PMICs, but having some axp22x variables
> right in the middle. And that's awfully inconsistent.
> 
> I'd rather have you add the AXP20x driver directly, and then add the
> needed stuff for the AXP22x.

>From a very quick look at the patch it looks like only basic
"monitoring" features have been retained, and yes, claiming the driver
to be for axp22x and having the functions named axp20x feels weird.

Missing parts are OCV, charge control (be it as interaction with
USB-power where charge current must be limited to not over-drain
USB power source or manual control when user knows more about the USB
power plug than the device).

Proper capacity measurement is a completely different story which I
did not implement (it exists in 3.4 sunxi kernel but is not
straight-forward and makes use of extra registers for data keeping).

Bruno

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05 12:45               ` Bruno Prémont
  0 siblings, 0 replies; 34+ messages in thread
From: Bruno Prémont @ 2016-07-05 12:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Icenowy Zheng, Michael Haas, wens-jdAy2FN1RRM,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	Mark Rutland, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

On Tue, 5 Jul 2016 11:25:10 +0200 Maxime Ripard wrote:
> On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
> > 
> > 
> > 05.07.2016, 13:26, "Michael Haas" <michael.haas-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>:  
> > > Hi,
> > >
> > > 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
> > > ready for submission. Do you know what pieces are missing in your driver
> > > for axp20x support - as opposed to axp22x, which is already working?  
> > 
> > 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.  
> 
> Still, it looks like you just took Bruno's driver, stripped out the
> axp20x parts and added the one to deal with axp22x.
> 
> This makes the driver look weird, by being called axp20x, without
> actually supporting those PMICs, but having some axp22x variables
> right in the middle. And that's awfully inconsistent.
> 
> I'd rather have you add the AXP20x driver directly, and then add the
> needed stuff for the AXP22x.

>From a very quick look at the patch it looks like only basic
"monitoring" features have been retained, and yes, claiming the driver
to be for axp22x and having the functions named axp20x feels weird.

Missing parts are OCV, charge control (be it as interaction with
USB-power where charge current must be limited to not over-drain
USB power source or manual control when user knows more about the USB
power plug than the device).

Proper capacity measurement is a completely different story which I
did not implement (it exists in 3.4 sunxi kernel but is not
straight-forward and makes use of extra registers for data keeping).

Bruno

-- 
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.

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-05 12:45               ` Bruno Prémont
  0 siblings, 0 replies; 34+ messages in thread
From: Bruno Prémont @ 2016-07-05 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 5 Jul 2016 11:25:10 +0200 Maxime Ripard wrote:
> On Tue, Jul 05, 2016 at 04:33:31PM +0800, Icenowy Zheng wrote:
> > 
> > 
> > 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
> > > axp20x?
> > >
> > > I've got a reworked version of that lying around, but it's not quite
> > > ready for submission. Do you know what pieces are missing in your driver
> > > for axp20x support - as opposed to axp22x, which is already working?  
> > 
> > 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.  
> 
> Still, it looks like you just took Bruno's driver, stripped out the
> axp20x parts and added the one to deal with axp22x.
> 
> This makes the driver look weird, by being called axp20x, without
> actually supporting those PMICs, but having some axp22x variables
> right in the middle. And that's awfully inconsistent.
> 
> I'd rather have you add the AXP20x driver directly, and then add the
> needed stuff for the AXP22x.

>From a very quick look at the patch it looks like only basic
"monitoring" features have been retained, and yes, claiming the driver
to be for axp22x and having the functions named axp20x feels weird.

Missing parts are OCV, charge control (be it as interaction with
USB-power where charge current must be limited to not over-drain
USB power source or manual control when user knows more about the USB
power plug than the device).

Proper capacity measurement is a completely different story which I
did not implement (it exists in 3.4 sunxi kernel but is not
straight-forward and makes use of extra registers for data keeping).

Bruno

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

* Re: [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-06  4:34             ` Michael Haas
  0 siblings, 0 replies; 34+ messages in thread
From: Michael Haas @ 2016-07-06  4:34 UTC (permalink / raw)
  To: icenowy, wens, maxime.ripard, sre, dbaryshkov, dwmw2
  Cc: robh+dt, mark.rutland, linux, devicetree, linux-arm-kernel,
	linux-kernel, linux-pm, linux-sunxi

Hi There,

On 05.07.2016 10:33, Icenowy Zheng wrote:
> On 01.07.2016 11:29, Icenowy Zheng wrote:

>>>   +
>>>   +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,
>>>   +};

Here's what Bruno's driver supports:

static enum power_supply_property axp20x_battery_power_properties[] = {
     POWER_SUPPLY_PROP_PRESENT,
     POWER_SUPPLY_PROP_ONLINE,
     POWER_SUPPLY_PROP_STATUS,
     POWER_SUPPLY_PROP_VOLTAGE_NOW,
     POWER_SUPPLY_PROP_CURRENT_NOW,
     POWER_SUPPLY_PROP_CURRENT_MAX,
     POWER_SUPPLY_PROP_HEALTH,
     POWER_SUPPLY_PROP_TECHNOLOGY,
     POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
     POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
     /* POWER_SUPPLY_PROP_POWER_NOW, */
     POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
     /* POWER_SUPPLY_PROP_CHARGE_NOW, */
     POWER_SUPPLY_PROP_CAPACITY,
     POWER_SUPPLY_PROP_TEMP,
     POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
     POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
};

>>>   +
>>>   +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 };


And here are the interrupts handled:

static const char * const irq_names[] = { "BATT_HOT", "BATT_COLD",
         "BATT_PLUGIN", "BATT_REMOVAL", "BATT_ACTIVATE",
         "BATT_ACTIVATED", "BATT_CHARGING", "BATT_CHARGED",
         "BATT_CHG_CURR_LOW", "BATT_POWER_LOW_WARN",
         "BATT_POWER_LOW_CRIT" };



There are a couple of issues with the version of Bruno's driver that I have:

* power management is disabled (in the driver, not in the charger) - 
think suspend/resume
* the temperature sensor data is not turned into a temperature value 
correctly
* the IRQ handlers need to be cleaned up (remove logging)
* device tree binding documentation is missing

Other than that, it's basically working and I have been using it at 
least for some testing.

The device tree bindings support:
* OCV curve support
* battery resistance
* battery capacity
* temp sensor settings

You can find my copy of Bruno's driver here:
https://github.com/mhaas/linux-sunxi/blob/axp209-charger/drivers/power/axp20x_fuel_gauge.c

Thanks,

Michael

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-06  4:34             ` Michael Haas
  0 siblings, 0 replies; 34+ messages in thread
From: Michael Haas @ 2016-07-06  4:34 UTC (permalink / raw)
  To: icenowy-ymACFijhrKM, wens-jdAy2FN1RRM,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

Hi There,

On 05.07.2016 10:33, Icenowy Zheng wrote:
> On 01.07.2016 11:29, Icenowy Zheng wrote:

>>>   +
>>>   +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,
>>>   +};

Here's what Bruno's driver supports:

static enum power_supply_property axp20x_battery_power_properties[] = {
     POWER_SUPPLY_PROP_PRESENT,
     POWER_SUPPLY_PROP_ONLINE,
     POWER_SUPPLY_PROP_STATUS,
     POWER_SUPPLY_PROP_VOLTAGE_NOW,
     POWER_SUPPLY_PROP_CURRENT_NOW,
     POWER_SUPPLY_PROP_CURRENT_MAX,
     POWER_SUPPLY_PROP_HEALTH,
     POWER_SUPPLY_PROP_TECHNOLOGY,
     POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
     POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
     /* POWER_SUPPLY_PROP_POWER_NOW, */
     POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
     /* POWER_SUPPLY_PROP_CHARGE_NOW, */
     POWER_SUPPLY_PROP_CAPACITY,
     POWER_SUPPLY_PROP_TEMP,
     POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
     POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
};

>>>   +
>>>   +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 };


And here are the interrupts handled:

static const char * const irq_names[] = { "BATT_HOT", "BATT_COLD",
         "BATT_PLUGIN", "BATT_REMOVAL", "BATT_ACTIVATE",
         "BATT_ACTIVATED", "BATT_CHARGING", "BATT_CHARGED",
         "BATT_CHG_CURR_LOW", "BATT_POWER_LOW_WARN",
         "BATT_POWER_LOW_CRIT" };



There are a couple of issues with the version of Bruno's driver that I have:

* power management is disabled (in the driver, not in the charger) - 
think suspend/resume
* the temperature sensor data is not turned into a temperature value 
correctly
* the IRQ handlers need to be cleaned up (remove logging)
* device tree binding documentation is missing

Other than that, it's basically working and I have been using it at 
least for some testing.

The device tree bindings support:
* OCV curve support
* battery resistance
* battery capacity
* temp sensor settings

You can find my copy of Bruno's driver here:
https://github.com/mhaas/linux-sunxi/blob/axp209-charger/drivers/power/axp20x_fuel_gauge.c

Thanks,

Michael

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-06  4:34             ` Michael Haas
  0 siblings, 0 replies; 34+ messages in thread
From: Michael Haas @ 2016-07-06  4:34 UTC (permalink / raw)
  To: linux-arm-kernel

Hi There,

On 05.07.2016 10:33, Icenowy Zheng wrote:
> On 01.07.2016 11:29, Icenowy Zheng wrote:

>>>   +
>>>   +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,
>>>   +};

Here's what Bruno's driver supports:

static enum power_supply_property axp20x_battery_power_properties[] = {
     POWER_SUPPLY_PROP_PRESENT,
     POWER_SUPPLY_PROP_ONLINE,
     POWER_SUPPLY_PROP_STATUS,
     POWER_SUPPLY_PROP_VOLTAGE_NOW,
     POWER_SUPPLY_PROP_CURRENT_NOW,
     POWER_SUPPLY_PROP_CURRENT_MAX,
     POWER_SUPPLY_PROP_HEALTH,
     POWER_SUPPLY_PROP_TECHNOLOGY,
     POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
     POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
     /* POWER_SUPPLY_PROP_POWER_NOW, */
     POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
     /* POWER_SUPPLY_PROP_CHARGE_NOW, */
     POWER_SUPPLY_PROP_CAPACITY,
     POWER_SUPPLY_PROP_TEMP,
     POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
     POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
};

>>>   +
>>>   +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 };


And here are the interrupts handled:

static const char * const irq_names[] = { "BATT_HOT", "BATT_COLD",
         "BATT_PLUGIN", "BATT_REMOVAL", "BATT_ACTIVATE",
         "BATT_ACTIVATED", "BATT_CHARGING", "BATT_CHARGED",
         "BATT_CHG_CURR_LOW", "BATT_POWER_LOW_WARN",
         "BATT_POWER_LOW_CRIT" };



There are a couple of issues with the version of Bruno's driver that I have:

* power management is disabled (in the driver, not in the charger) - 
think suspend/resume
* the temperature sensor data is not turned into a temperature value 
correctly
* the IRQ handlers need to be cleaned up (remove logging)
* device tree binding documentation is missing

Other than that, it's basically working and I have been using it at 
least for some testing.

The device tree bindings support:
* OCV curve support
* battery resistance
* battery capacity
* temp sensor settings

You can find my copy of Bruno's driver here:
https://github.com/mhaas/linux-sunxi/blob/axp209-charger/drivers/power/axp20x_fuel_gauge.c

Thanks,

Michael

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

* Re: [PATCH 2/4] power: add axp20x-battery driver
  2016-07-06  4:34             ` Michael Haas
@ 2016-07-06  7:48                 ` Icenowy Zheng
  -1 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-06  7:48 UTC (permalink / raw)
  To: Michael Haas, wens-jdAy2FN1RRM,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw



06.07.2016, 12:35, "Michael Haas" <haas-bdq14YP6qtSV9CzYT+GlPGD2FQJk+8+b@public.gmane.org>:
> Hi There,
>
> On 05.07.2016 10:33, Icenowy Zheng wrote:
>>  On 01.07.2016 11:29, Icenowy Zheng wrote:
>
>>>>    +
>>>>    +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,
>>>>    +};
>
> Here's what Bruno's driver supports:
>
> static enum power_supply_property axp20x_battery_power_properties[] = {
>      POWER_SUPPLY_PROP_PRESENT,
>      POWER_SUPPLY_PROP_ONLINE,
>      POWER_SUPPLY_PROP_STATUS,
>      POWER_SUPPLY_PROP_VOLTAGE_NOW,
>      POWER_SUPPLY_PROP_CURRENT_NOW,
>      POWER_SUPPLY_PROP_CURRENT_MAX,
>      POWER_SUPPLY_PROP_HEALTH,
>      POWER_SUPPLY_PROP_TECHNOLOGY,
>      POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
>      POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
>      /* POWER_SUPPLY_PROP_POWER_NOW, */
>      POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
>      /* POWER_SUPPLY_PROP_CHARGE_NOW, */
>      POWER_SUPPLY_PROP_CAPACITY,
>      POWER_SUPPLY_PROP_TEMP,
>      POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
>      POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
> };
>
>>>>    +
>>>>    +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 };
>
> And here are the interrupts handled:
>
> static const char * const irq_names[] = { "BATT_HOT", "BATT_COLD",
>          "BATT_PLUGIN", "BATT_REMOVAL", "BATT_ACTIVATE",
>          "BATT_ACTIVATED", "BATT_CHARGING", "BATT_CHARGED",
>          "BATT_CHG_CURR_LOW", "BATT_POWER_LOW_WARN",
>          "BATT_POWER_LOW_CRIT" };
>
> There are a couple of issues with the version of Bruno's driver that I have:
>
> * power management is disabled (in the driver, not in the charger) -
> think suspend/resume
> * the temperature sensor data is not turned into a temperature value
> correctly
> * the IRQ handlers need to be cleaned up (remove logging)
> * device tree binding documentation is missing
>
> Other than that, it's basically working and I have been using it at
> least for some testing.
>
> The device tree bindings support:
> * OCV curve support
> * battery resistance
> * battery capacity
> * temp sensor settings
>
> You can find my copy of Bruno's driver here:
> https://github.com/mhaas/linux-sunxi/blob/axp209-charger/drivers/power/axp20x_fuel_gauge.c
>
> Thanks,
>
> Michael

Michael Haas:
I'm grateful for you providing your axp20x_fuel_gauge.c copy.

I will try to tidy it up and add support for axp22x.

Thanks,

Icenowy

-- 
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.

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

* [linux-sunxi] [PATCH 2/4] power: add axp20x-battery driver
@ 2016-07-06  7:48                 ` Icenowy Zheng
  0 siblings, 0 replies; 34+ messages in thread
From: Icenowy Zheng @ 2016-07-06  7:48 UTC (permalink / raw)
  To: linux-arm-kernel



06.07.2016, 12:35, "Michael Haas" <haas@computerlinguist.org>:
> Hi There,
>
> On 05.07.2016 10:33, Icenowy Zheng wrote:
>> ?On 01.07.2016 11:29, Icenowy Zheng wrote:
>
>>>> ???+
>>>> ???+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,
>>>> ???+};
>
> Here's what Bruno's driver supports:
>
> static enum power_supply_property axp20x_battery_power_properties[] = {
> ?????POWER_SUPPLY_PROP_PRESENT,
> ?????POWER_SUPPLY_PROP_ONLINE,
> ?????POWER_SUPPLY_PROP_STATUS,
> ?????POWER_SUPPLY_PROP_VOLTAGE_NOW,
> ?????POWER_SUPPLY_PROP_CURRENT_NOW,
> ?????POWER_SUPPLY_PROP_CURRENT_MAX,
> ?????POWER_SUPPLY_PROP_HEALTH,
> ?????POWER_SUPPLY_PROP_TECHNOLOGY,
> ?????POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
> ?????POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
> ?????/* POWER_SUPPLY_PROP_POWER_NOW, */
> ?????POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
> ?????/* POWER_SUPPLY_PROP_CHARGE_NOW, */
> ?????POWER_SUPPLY_PROP_CAPACITY,
> ?????POWER_SUPPLY_PROP_TEMP,
> ?????POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
> ?????POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
> };
>
>>>> ???+
>>>> ???+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 };
>
> And here are the interrupts handled:
>
> static const char * const irq_names[] = { "BATT_HOT", "BATT_COLD",
> ?????????"BATT_PLUGIN", "BATT_REMOVAL", "BATT_ACTIVATE",
> ?????????"BATT_ACTIVATED", "BATT_CHARGING", "BATT_CHARGED",
> ?????????"BATT_CHG_CURR_LOW", "BATT_POWER_LOW_WARN",
> ?????????"BATT_POWER_LOW_CRIT" };
>
> There are a couple of issues with the version of Bruno's driver that I have:
>
> * power management is disabled (in the driver, not in the charger) -
> think suspend/resume
> * the temperature sensor data is not turned into a temperature value
> correctly
> * the IRQ handlers need to be cleaned up (remove logging)
> * device tree binding documentation is missing
>
> Other than that, it's basically working and I have been using it at
> least for some testing.
>
> The device tree bindings support:
> * OCV curve support
> * battery resistance
> * battery capacity
> * temp sensor settings
>
> You can find my copy of Bruno's driver here:
> https://github.com/mhaas/linux-sunxi/blob/axp209-charger/drivers/power/axp20x_fuel_gauge.c
>
> Thanks,
>
> Michael

Michael Haas:
I'm grateful for you providing your axp20x_fuel_gauge.c copy.

I will try to tidy it up and add support for axp22x.

Thanks,

Icenowy

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

* Re: [PATCH 1/4] mfd: axp20x: add adc volatile ranges for axp22x
       [not found] ` <20160701092926.32005-1-icenowy-ymACFijhrKM@public.gmane.org>
  2016-07-01  9:29     ` Icenowy Zheng
@ 2016-08-05  7:46   ` Lee Jones
  2016-07-01  9:29     ` Icenowy Zheng
  2 siblings, 0 replies; 34+ messages in thread
From: Lee Jones @ 2016-08-05  7:46 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: wens, maxime.ripard, sre, dbaryshkov, dwmw2, mark.rutland,
	devicetree, linux-pm, linux, linux-kernel, linux-sunxi, robh+dt,
	linux-arm-kernel

On Fri, 01 Jul 2016, Icenowy Zheng wrote:

> AXP22x has also some different register map than axp20x, they're also
> added here.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
>  drivers/mfd/axp20x.c       | 1 +
>  include/linux/mfd/axp20x.h | 4 ++++
>  2 files changed, 5 insertions(+)

Applied, thanks.

> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index d62209d..cee5288 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -96,6 +96,7 @@ static const struct regmap_range axp22x_volatile_ranges[] = {
>  	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
>  	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
>  	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
> +	regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
>  	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
>  };
>  
> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
> index 0be4982..ad3d9c7 100644
> --- a/include/linux/mfd/axp20x.h
> +++ b/include/linux/mfd/axp20x.h
> @@ -201,6 +201,10 @@ enum {
>  #define AXP20X_OCV_MAX			0xf
>  
>  /* AXP22X specific registers */
> +#define AXP22X_PMIC_ADC_H		0x56
> +#define AXP22X_PMIC_ADC_L		0x57
> +#define AXP22X_TS_ADC_H			0x58
> +#define AXP22X_TS_ADC_L			0x59
>  #define AXP22X_BATLOW_THRES1		0xe6
>  
>  /* AXP288 specific registers */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH 1/4] mfd: axp20x: add adc volatile ranges for axp22x
@ 2016-08-05  7:46   ` Lee Jones
  0 siblings, 0 replies; 34+ messages in thread
From: Lee Jones @ 2016-08-05  7:46 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: wens-jdAy2FN1RRM, maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	sre-DgEjT+Ai2ygdnm+yROfE0A, dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pm-u79uwXL29TY76Z2rM5mHXA, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Fri, 01 Jul 2016, Icenowy Zheng wrote:

> AXP22x has also some different register map than axp20x, they're also
> added here.
> 
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> ---
>  drivers/mfd/axp20x.c       | 1 +
>  include/linux/mfd/axp20x.h | 4 ++++
>  2 files changed, 5 insertions(+)

Applied, thanks.

> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index d62209d..cee5288 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -96,6 +96,7 @@ static const struct regmap_range axp22x_volatile_ranges[] = {
>  	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
>  	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
>  	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
> +	regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
>  	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
>  };
>  
> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
> index 0be4982..ad3d9c7 100644
> --- a/include/linux/mfd/axp20x.h
> +++ b/include/linux/mfd/axp20x.h
> @@ -201,6 +201,10 @@ enum {
>  #define AXP20X_OCV_MAX			0xf
>  
>  /* AXP22X specific registers */
> +#define AXP22X_PMIC_ADC_H		0x56
> +#define AXP22X_PMIC_ADC_L		0x57
> +#define AXP22X_TS_ADC_H			0x58
> +#define AXP22X_TS_ADC_L			0x59
>  #define AXP22X_BATLOW_THRES1		0xe6
>  
>  /* AXP288 specific registers */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

-- 
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.

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

* [PATCH 1/4] mfd: axp20x: add adc volatile ranges for axp22x
@ 2016-08-05  7:46   ` Lee Jones
  0 siblings, 0 replies; 34+ messages in thread
From: Lee Jones @ 2016-08-05  7:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 01 Jul 2016, Icenowy Zheng wrote:

> AXP22x has also some different register map than axp20x, they're also
> added here.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
>  drivers/mfd/axp20x.c       | 1 +
>  include/linux/mfd/axp20x.h | 4 ++++
>  2 files changed, 5 insertions(+)

Applied, thanks.

> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index d62209d..cee5288 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -96,6 +96,7 @@ static const struct regmap_range axp22x_volatile_ranges[] = {
>  	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
>  	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
>  	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
> +	regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
>  	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
>  };
>  
> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
> index 0be4982..ad3d9c7 100644
> --- a/include/linux/mfd/axp20x.h
> +++ b/include/linux/mfd/axp20x.h
> @@ -201,6 +201,10 @@ enum {
>  #define AXP20X_OCV_MAX			0xf
>  
>  /* AXP22X specific registers */
> +#define AXP22X_PMIC_ADC_H		0x56
> +#define AXP22X_PMIC_ADC_L		0x57
> +#define AXP22X_TS_ADC_H			0x58
> +#define AXP22X_TS_ADC_L			0x59
>  #define AXP22X_BATLOW_THRES1		0xe6
>  
>  /* AXP288 specific registers */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

end of thread, other threads:[~2016-08-05  7:46 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-01  9:29 [PATCH 1/4] mfd: axp20x: add adc volatile ranges for axp22x Icenowy Zheng
2016-07-01  9:29 ` Icenowy Zheng
     [not found] ` <20160701092926.32005-1-icenowy-ymACFijhrKM@public.gmane.org>
2016-07-01  9:29   ` [PATCH 2/4] power: add axp20x-battery driver Icenowy Zheng
2016-07-01  9:29     ` Icenowy Zheng
2016-07-05  5:26     ` [linux-sunxi] " Michael Haas
2016-07-05  5:26       ` Michael Haas
2016-07-05  5:26       ` Michael Haas
     [not found]       ` <577B44FD.6040404-cl+VPiYnx/1AfugRpC6u6w@public.gmane.org>
2016-07-05  8:33         ` Icenowy Zheng
2016-07-05  8:33           ` [linux-sunxi] " Icenowy Zheng
2016-07-05  9:25           ` maxime.ripard
2016-07-05  9:25             ` maxime.ripard at free-electrons.com
2016-07-05  9:25             ` maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
2016-07-05 10:09             ` Icenowy Zheng
2016-07-05 10:09               ` [linux-sunxi] " Icenowy Zheng
2016-07-05 12:45             ` Bruno Prémont
2016-07-05 12:45               ` Bruno Prémont
2016-07-05 12:45               ` Bruno Prémont
2016-07-06  4:34           ` [linux-sunxi] " Michael Haas
2016-07-06  4:34             ` Michael Haas
2016-07-06  4:34             ` Michael Haas
     [not found]             ` <577C8A6D.8000409-bdq14YP6qtSV9CzYT+GlPGD2FQJk+8+b@public.gmane.org>
2016-07-06  7:48               ` Icenowy Zheng
2016-07-06  7:48                 ` [linux-sunxi] " Icenowy Zheng
2016-07-05  8:47         ` Icenowy Zheng
2016-07-05  8:47           ` [linux-sunxi] " Icenowy Zheng
2016-07-05 12:43           ` Bruno Prémont
2016-07-05 12:43             ` Bruno Prémont
2016-07-05 12:43             ` Bruno Prémont
2016-07-01  9:29   ` [PATCH 3/4] ARM: sun8i: add axp20x-battery node for axp22x Icenowy Zheng
2016-07-01  9:29     ` Icenowy Zheng
2016-07-01  9:29   ` [PATCH 4/4] ARM: sun8i: enable axp22x-battery on A23/33 Q8 tablets Icenowy Zheng
2016-07-01  9:29     ` Icenowy Zheng
2016-08-05  7:46 ` [PATCH 1/4] mfd: axp20x: add adc volatile ranges for axp22x Lee Jones
2016-08-05  7:46   ` Lee Jones
2016-08-05  7:46   ` Lee Jones

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.