Linux-OMAP Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] drivers: power_supply: cpcap-battery: Add battery type auto detection for mapphone devices
@ 2021-01-17 22:38 Carl Philipp Klemm
  2021-04-05  8:44 ` Sebastian Reichel
  0 siblings, 1 reply; 2+ messages in thread
From: Carl Philipp Klemm @ 2021-01-17 22:38 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: linux-pm, linux-omap, Arthur Demchenkov, Tony Lindgren,
	Merlijn Wajer, Pavel Machek

This allow cpcap-battery to detect whitch battery is inserted, HW4X or BW8X for
xt875 and EB41 for xt894 by examining the battery nvmem. If no known battery
is detected sane defaults are used.

Signed-off-by: Carl Philipp Klemm <philipp@uvos.xyz>
---
 drivers/power/supply/cpcap-battery.c | 117 ++++++++++++++++++++-------
 1 file changed, 90 insertions(+), 27 deletions(-)

diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c
index 8ae0c9c7ebcb..4bd7c71c6abe 100644
--- a/drivers/power/supply/cpcap-battery.c
+++ b/drivers/power/supply/cpcap-battery.c
@@ -28,6 +28,7 @@
 #include <linux/power_supply.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/moduleparam.h>
 
 #include <linux/iio/consumer.h>
@@ -73,6 +74,9 @@
 
 #define CPCAP_BATTERY_CC_SAMPLE_PERIOD_MS	250
 
+#define CPCAP_BATTERY_EB41_HW4X_ID 0x9E
+#define CPCAP_BATTERY_BW8X_ID 0x98
+
 enum {
 	CPCAP_BATTERY_IIO_BATTDET,
 	CPCAP_BATTERY_IIO_VOLTAGE,
@@ -97,6 +101,7 @@ struct cpcap_interrupt_desc {
 
 struct cpcap_battery_config {
 	int cd_factor;
+	char id;
 	struct power_supply_info info;
 	struct power_supply_battery_info bat;
 };
@@ -138,6 +143,7 @@ struct cpcap_battery_ddata {
 	int charge_full;
 	int status;
 	u16 vendor;
+	bool check_nvmem;
 	unsigned int is_full:1;
 };
 
@@ -146,6 +152,50 @@ struct cpcap_battery_ddata {
 static bool ignore_temperature_probe;
 module_param(ignore_temperature_probe, bool, 0660);
 
+/*
+ * Based on the values from Motorola mapphone Linux kernel for the
+ * stock Droid 4 battery eb41. In the Motorola mapphone Linux
+ * kernel tree the value for pm_cd_factor is passed to the kernel
+ * via device tree. If it turns out to be something device specific
+ * we can consider that too later. These values are also fine for
+ * Bionic's hw4x.
+ *
+ * And looking at the battery full and shutdown values for the stock
+ * kernel on droid 4, full is 4351000 and software initiates shutdown
+ * at 3078000. The device will die around 2743000.
+ */
+static const struct cpcap_battery_config cpcap_battery_eb41_data = {
+	.cd_factor = 0x3cc,
+	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
+	.info.voltage_max_design = 4351000,
+	.info.voltage_min_design = 3100000,
+	.info.charge_full_design = 1740000,
+	.bat.constant_charge_voltage_max_uv = 4200000,
+};
+
+/* Values for the extended Droid Bionic battery bw8x. */
+static const struct cpcap_battery_config cpcap_battery_bw8x_data = {
+	.cd_factor = 0x3cc,
+	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
+	.info.voltage_max_design = 4200000,
+	.info.voltage_min_design = 3200000,
+	.info.charge_full_design = 2760000,
+	.bat.constant_charge_voltage_max_uv = 4200000,
+};
+
+/*
+ * Safe values for any lipo battery likely to fit into a mapphone
+ * battery bay.
+ */
+static const struct cpcap_battery_config cpcap_battery_unkown_data = {
+	.cd_factor = 0x3cc,
+	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
+	.info.voltage_max_design = 4200000,
+	.info.voltage_min_design = 3200000,
+	.info.charge_full_design = 3000000,
+	.bat.constant_charge_voltage_max_uv = 4200000,
+};
+
 static struct cpcap_battery_state_data *
 cpcap_battery_get_state(struct cpcap_battery_ddata *ddata,
 			enum cpcap_battery_state state)
@@ -531,6 +581,41 @@ static void cpcap_battery_external_power_changed(struct power_supply *psy)
 	power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &prop);
 }
 
+static int cpcap_battery_match_nvmem(struct device *dev, const void *data)
+{
+	if (strcmp(dev_name(dev), "89-500029ba0f73") == 0)
+		return 1;
+	else
+		return 0;
+}
+
+static void cpcap_battery_detect_battery_type(struct cpcap_battery_ddata *ddata)
+{
+	struct nvmem_device *nvmem;
+	u8 battery_id = 0;
+
+	ddata->check_nvmem = false;
+
+	nvmem = nvmem_device_find(NULL, &cpcap_battery_match_nvmem);
+	if (IS_ERR_OR_NULL(nvmem)) {
+		ddata->check_nvmem = true;
+	} else if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) {
+		battery_id = 0;
+		ddata->check_nvmem = true;
+	}
+
+	switch (battery_id) {
+	case CPCAP_BATTERY_EB41_HW4X_ID:
+		memcpy(&ddata->config, &cpcap_battery_eb41_data, sizeof(ddata->config));
+		break;
+	case CPCAP_BATTERY_BW8X_ID:
+		memcpy(&ddata->config, &cpcap_battery_bw8x_data, sizeof(ddata->config));
+		break;
+	default:
+		memcpy(&ddata->config, &cpcap_battery_unkown_data, sizeof(ddata->config));
+	}
+}
+
 static enum power_supply_property cpcap_battery_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
@@ -564,6 +649,9 @@ static int cpcap_battery_get_property(struct power_supply *psy,
 	int cached;
 	s64 tmp;
 
+	if (ddata->check_nvmem)
+		cpcap_battery_detect_battery_type(ddata);
+
 	cached = cpcap_battery_update_status(ddata);
 	if (cached < 0)
 		return cached;
@@ -981,30 +1069,10 @@ static int cpcap_battery_calibrate(struct cpcap_battery_ddata *ddata)
 	return error;
 }
 
-/*
- * Based on the values from Motorola mapphone Linux kernel. In the
- * the Motorola mapphone Linux kernel tree the value for pm_cd_factor
- * is passed to the kernel via device tree. If it turns out to be
- * something device specific we can consider that too later.
- *
- * And looking at the battery full and shutdown values for the stock
- * kernel on droid 4, full is 4351000 and software initiates shutdown
- * at 3078000. The device will die around 2743000.
- */
-static const struct cpcap_battery_config cpcap_battery_default_data = {
-	.cd_factor = 0x3cc,
-	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
-	.info.voltage_max_design = 4351000,
-	.info.voltage_min_design = 3100000,
-	.info.charge_full_design = 1740000,
-	.bat.constant_charge_voltage_max_uv = 4200000,
-};
-
 #ifdef CONFIG_OF
 static const struct of_device_id cpcap_battery_id_table[] = {
 	{
 		.compatible = "motorola,cpcap-battery",
-		.data = &cpcap_battery_default_data,
 	},
 	{},
 };
@@ -1024,19 +1092,14 @@ static int cpcap_battery_probe(struct platform_device *pdev)
 	if (!match)
 		return -EINVAL;
 
-	if (!match->data) {
-		dev_err(&pdev->dev, "no configuration data found\n");
-
-		return -ENODEV;
-	}
-
 	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
 	if (!ddata)
 		return -ENOMEM;
 
+	cpcap_battery_detect_battery_type(ddata);
+
 	INIT_LIST_HEAD(&ddata->irq_list);
 	ddata->dev = &pdev->dev;
-	memcpy(&ddata->config, match->data, sizeof(ddata->config));
 
 	ddata->reg = dev_get_regmap(ddata->dev->parent, NULL);
 	if (!ddata->reg)
-- 
2.29.2

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

* Re: [PATCH] drivers: power_supply: cpcap-battery: Add battery type auto detection for mapphone devices
  2021-01-17 22:38 [PATCH] drivers: power_supply: cpcap-battery: Add battery type auto detection for mapphone devices Carl Philipp Klemm
@ 2021-04-05  8:44 ` Sebastian Reichel
  0 siblings, 0 replies; 2+ messages in thread
From: Sebastian Reichel @ 2021-04-05  8:44 UTC (permalink / raw)
  To: Carl Philipp Klemm
  Cc: linux-pm, linux-omap, Arthur Demchenkov, Tony Lindgren,
	Merlijn Wajer, Pavel Machek


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

Hi,

On Sun, Jan 17, 2021 at 11:38:39PM +0100, Carl Philipp Klemm wrote:
> This allow cpcap-battery to detect whitch battery is inserted, HW4X or BW8X for
> xt875 and EB41 for xt894 by examining the battery nvmem. If no known battery
> is detected sane defaults are used.

Idea sounds very good to me :)

> Signed-off-by: Carl Philipp Klemm <philipp@uvos.xyz>
> ---
>  drivers/power/supply/cpcap-battery.c | 117 ++++++++++++++++++++-------
>  1 file changed, 90 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c
> index 8ae0c9c7ebcb..4bd7c71c6abe 100644
> --- a/drivers/power/supply/cpcap-battery.c
> +++ b/drivers/power/supply/cpcap-battery.c
> @@ -28,6 +28,7 @@
>  #include <linux/power_supply.h>
>  #include <linux/reboot.h>
>  #include <linux/regmap.h>
> +#include <linux/nvmem-consumer.h>

You need to add at least

depends on NVMEM || !NVMEM

to the cpcap-battery Kconfig symbol. This marks the config
CPCAP_BATTERY=y && NVMEM=m as invalid. But considering we
expect batteries to have the NVMEM it might be better to
just add

depends on NVMEM

even though code works without NVMEM to some degree.

>  #include <linux/moduleparam.h>
>  
>  #include <linux/iio/consumer.h>
> @@ -73,6 +74,9 @@
>  
>  #define CPCAP_BATTERY_CC_SAMPLE_PERIOD_MS	250
>  
> +#define CPCAP_BATTERY_EB41_HW4X_ID 0x9E
> +#define CPCAP_BATTERY_BW8X_ID 0x98
> +
>  enum {
>  	CPCAP_BATTERY_IIO_BATTDET,
>  	CPCAP_BATTERY_IIO_VOLTAGE,
> @@ -97,6 +101,7 @@ struct cpcap_interrupt_desc {
>  
>  struct cpcap_battery_config {
>  	int cd_factor;
> +	char id;

This is not being used anywhere, please drop.

>  	struct power_supply_info info;
>  	struct power_supply_battery_info bat;
>  };
> @@ -138,6 +143,7 @@ struct cpcap_battery_ddata {
>  	int charge_full;
>  	int status;
>  	u16 vendor;
> +	bool check_nvmem;
>  	unsigned int is_full:1;
>  };
>  
> @@ -146,6 +152,50 @@ struct cpcap_battery_ddata {
>  static bool ignore_temperature_probe;
>  module_param(ignore_temperature_probe, bool, 0660);
>  
> +/*
> + * Based on the values from Motorola mapphone Linux kernel for the
> + * stock Droid 4 battery eb41. In the Motorola mapphone Linux
> + * kernel tree the value for pm_cd_factor is passed to the kernel
> + * via device tree. If it turns out to be something device specific
> + * we can consider that too later. These values are also fine for
> + * Bionic's hw4x.
> + *
> + * And looking at the battery full and shutdown values for the stock
> + * kernel on droid 4, full is 4351000 and software initiates shutdown
> + * at 3078000. The device will die around 2743000.
> + */
> +static const struct cpcap_battery_config cpcap_battery_eb41_data = {
> +	.cd_factor = 0x3cc,
> +	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
> +	.info.voltage_max_design = 4351000,
> +	.info.voltage_min_design = 3100000,
> +	.info.charge_full_design = 1740000,
> +	.bat.constant_charge_voltage_max_uv = 4200000,
> +};
> +
> +/* Values for the extended Droid Bionic battery bw8x. */
> +static const struct cpcap_battery_config cpcap_battery_bw8x_data = {
> +	.cd_factor = 0x3cc,
> +	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
> +	.info.voltage_max_design = 4200000,
> +	.info.voltage_min_design = 3200000,
> +	.info.charge_full_design = 2760000,
> +	.bat.constant_charge_voltage_max_uv = 4200000,
> +};
> +
> +/*
> + * Safe values for any lipo battery likely to fit into a mapphone
> + * battery bay.
> + */
> +static const struct cpcap_battery_config cpcap_battery_unkown_data = {
> +	.cd_factor = 0x3cc,
> +	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
> +	.info.voltage_max_design = 4200000,
> +	.info.voltage_min_design = 3200000,
> +	.info.charge_full_design = 3000000,
> +	.bat.constant_charge_voltage_max_uv = 4200000,
> +};
> +
>  static struct cpcap_battery_state_data *
>  cpcap_battery_get_state(struct cpcap_battery_ddata *ddata,
>  			enum cpcap_battery_state state)
> @@ -531,6 +581,41 @@ static void cpcap_battery_external_power_changed(struct power_supply *psy)
>  	power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &prop);
>  }
>  
> +static int cpcap_battery_match_nvmem(struct device *dev, const void *data)
> +{
> +	if (strcmp(dev_name(dev), "89-500029ba0f73") == 0)
> +		return 1;
> +	else
> +		return 0;
> +}
> +
> +static void cpcap_battery_detect_battery_type(struct cpcap_battery_ddata *ddata)
> +{
> +	struct nvmem_device *nvmem;
> +	u8 battery_id = 0;
> +
> +	ddata->check_nvmem = false;
> +
> +	nvmem = nvmem_device_find(NULL, &cpcap_battery_match_nvmem);
> +	if (IS_ERR_OR_NULL(nvmem)) {
> +		ddata->check_nvmem = true;
> +	} else if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) {
> +		battery_id = 0;
> +		ddata->check_nvmem = true;
> +	}

Can we print warnings for the above problems or are there batteries
without nvmem?

> +	switch (battery_id) {
> +	case CPCAP_BATTERY_EB41_HW4X_ID:
> +		memcpy(&ddata->config, &cpcap_battery_eb41_data, sizeof(ddata->config));
> +		break;
> +	case CPCAP_BATTERY_BW8X_ID:
> +		memcpy(&ddata->config, &cpcap_battery_bw8x_data, sizeof(ddata->config));
> +		break;
> +	default:
> +		memcpy(&ddata->config, &cpcap_battery_unkown_data, sizeof(ddata->config));
> +	}
> +}
> +
>  static enum power_supply_property cpcap_battery_props[] = {
>  	POWER_SUPPLY_PROP_STATUS,
>  	POWER_SUPPLY_PROP_PRESENT,
> @@ -564,6 +649,9 @@ static int cpcap_battery_get_property(struct power_supply *psy,
>  	int cached;
>  	s64 tmp;
>  
> +	if (ddata->check_nvmem)
> +		cpcap_battery_detect_battery_type(ddata);
> +
>  	cached = cpcap_battery_update_status(ddata);
>  	if (cached < 0)
>  		return cached;
> @@ -981,30 +1069,10 @@ static int cpcap_battery_calibrate(struct cpcap_battery_ddata *ddata)
>  	return error;
>  }
>  
> -/*
> - * Based on the values from Motorola mapphone Linux kernel. In the
> - * the Motorola mapphone Linux kernel tree the value for pm_cd_factor
> - * is passed to the kernel via device tree. If it turns out to be
> - * something device specific we can consider that too later.
> - *
> - * And looking at the battery full and shutdown values for the stock
> - * kernel on droid 4, full is 4351000 and software initiates shutdown
> - * at 3078000. The device will die around 2743000.
> - */
> -static const struct cpcap_battery_config cpcap_battery_default_data = {
> -	.cd_factor = 0x3cc,
> -	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,
> -	.info.voltage_max_design = 4351000,
> -	.info.voltage_min_design = 3100000,
> -	.info.charge_full_design = 1740000,
> -	.bat.constant_charge_voltage_max_uv = 4200000,
> -};
> -
>  #ifdef CONFIG_OF
>  static const struct of_device_id cpcap_battery_id_table[] = {
>  	{
>  		.compatible = "motorola,cpcap-battery",
> -		.data = &cpcap_battery_default_data,
>  	},
>  	{},
>  };
> @@ -1024,19 +1092,14 @@ static int cpcap_battery_probe(struct platform_device *pdev)
>  	if (!match)
>  		return -EINVAL;

Please remove all match related stuff; it was only required for
accessing match->data.

> -	if (!match->data) {
> -		dev_err(&pdev->dev, "no configuration data found\n");
> -
> -		return -ENODEV;
> -	}
> -
>  	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
>  	if (!ddata)
>  		return -ENOMEM;
>  
> +	cpcap_battery_detect_battery_type(ddata);
> +
>  	INIT_LIST_HEAD(&ddata->irq_list);
>  	ddata->dev = &pdev->dev;
> -	memcpy(&ddata->config, match->data, sizeof(ddata->config));
>  
>  	ddata->reg = dev_get_regmap(ddata->dev->parent, NULL);
>  	if (!ddata->reg)
> -- 
> 2.29.2

Thanks,

-- Sebastian

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

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

end of thread, back to index

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-17 22:38 [PATCH] drivers: power_supply: cpcap-battery: Add battery type auto detection for mapphone devices Carl Philipp Klemm
2021-04-05  8:44 ` Sebastian Reichel

Linux-OMAP Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-omap/0 linux-omap/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-omap linux-omap/ https://lore.kernel.org/linux-omap \
		linux-omap@vger.kernel.org
	public-inbox-index linux-omap

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-omap


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git