Re: [PATCH v2 1/3] power_supply: modelgauge_battery: Maxim ModelGauge ICs gauge

2014-03-04 Thread Krzysztof Kozlowski
And one more comment:

On Sun, 2014-02-02 at 02:23 +0400, Vladimir Barinov wrote:
> +static int modelgauge_get_property(struct power_supply *psy,
> +enum power_supply_property psp,
> +union power_supply_propval *val)
> +{
> + struct modelgauge_priv *priv = container_of(psy,
> + struct modelgauge_priv,
> + battery);
> + struct regmap *regmap = priv->regmap;
> + struct modelgauge_platform_data *pdata = priv->pdata;
> + int reg;
> + int ret;
> +
> + switch (psp) {
> + case POWER_SUPPLY_PROP_STATUS:
> + if (pdata && pdata->get_charging_status)
> + val->intval = pdata->get_charging_status();
> + else
> + val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
> + break;
> + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
> + ret = regmap_read(regmap, MODELGAUGE_VCELL_REG, ®);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = modelgauge_lsb_to_uvolts(priv, reg);
> + break;
> + case POWER_SUPPLY_PROP_VOLTAGE_OCV:
> + /* Unlock model access */
> + regmap_write(regmap, MODELGAUGE_UNLOCK_REG,
> +  MODELGAUGE_UNLOCK_VALUE);
> + ret = regmap_read(regmap, MODELGAUGE_OCV_REG, ®);
> + /* Lock model access */
> + regmap_write(regmap, MODELGAUGE_UNLOCK_REG, 0);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = modelgauge_lsb_to_uvolts(priv, reg);
> + break;
> + case POWER_SUPPLY_PROP_CAPACITY:
> + ret = regmap_read(regmap, MODELGAUGE_SOC_REG, ®);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = reg / (1 << priv->soc_shift);
> + break;
> + case POWER_SUPPLY_PROP_TEMP:
> + if (pdata && pdata->get_temperature)
> + val->intval = pdata->get_temperature();
> + else
> + val->intval = 25;

If pdata->get_temperature() is not supplied then probably the driver
should not support POWER_SUPPLY_PROP_TEMP at all. I think it is better
not to report any temperature than to report a wrong one.


Best regards,
Krzysztof

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 1/3] power_supply: modelgauge_battery: Maxim ModelGauge ICs gauge

2014-03-04 Thread Krzysztof Kozlowski
Hi,

On Sun, 2014-02-02 at 02:23 +0400, Vladimir Barinov wrote:
> Index: battery-2.6/drivers/power/modelgauge_battery.c
> ===
> --- /dev/null 1970-01-01 00:00:00.0 +
> +++ battery-2.6/drivers/power/modelgauge_battery.c2014-02-02 
> 01:29:34.314614874 +0400
> @@ -0,0 +1,838 @@
> +/*
> + * Maxim ModelGauge ICs fuel gauge driver
> + *
> + * Author: Vladimir Barinov 
> + * Copyright (C) 2013 Cogent Embedded, Inc.
> + *
> + * 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.
> + */

(...)

> +static int modelgauge_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> + struct modelgauge_priv *priv;
> + int ret;
> +
> + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
> + return -EIO;
> +
> + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + if (client->dev.of_node)
> + priv->pdata = modelgauge_parse_dt(&client->dev);
> + else
> + priv->pdata = client->dev.platform_data;
> +
> + priv->dev   = &client->dev;
> + priv->chip  = id->driver_data;
> +
> + i2c_set_clientdata(client, priv);
> +
> + priv->regmap = devm_regmap_init_i2c(client, &modelgauge_regmap);
> + if (IS_ERR(priv->regmap))
> + return PTR_ERR(priv->regmap);
> +
> + priv->battery.name  = "modelgauge_battery";
> + priv->battery.type  = POWER_SUPPLY_TYPE_BATTERY;
> + priv->battery.get_property  = modelgauge_get_property;
> + priv->battery.properties= modelgauge_battery_props;
> + priv->battery.num_properties= ARRAY_SIZE(modelgauge_battery_props);
> +
> + INIT_WORK(&priv->load_work, modelgauge_load_model_work);
> + INIT_DELAYED_WORK(&priv->rcomp_work, modelgauge_update_rcomp_work);
> +
> + ret = modelgauge_init(priv);
> + if (ret)
> + return ret;
> +
> + ret = power_supply_register(&client->dev, &priv->battery);
> + if (ret) {
> + dev_err(priv->dev, "failed: power supply register\n");
> + goto err_supply;
> + }
> +
> + if (client->irq) {
> + switch (priv->chip) {
> + case ID_MAX17040:
> + case ID_MAX17041:
> + dev_err(priv->dev, "alert line is not supported\n");
> + ret = -EINVAL;
> + goto err_irq;
> + default:
> + ret = devm_request_threaded_irq(priv->dev, client->irq,
> + NULL,
> + modelgauge_irq_handler,
> + IRQF_TRIGGER_FALLING,
> + priv->battery.name,
> + priv);

Shouldn't it be also IRQF_ONESHOT? Without this you may get an error:
genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq

> + if (ret) {
> + dev_err(priv->dev, "failed to request irq %d\n",
> + client->irq);
> + goto err_irq;
> + }
> + }
> + }
> +
> + return 0;
> +
> +err_irq:
> + power_supply_unregister(&priv->battery);
> +err_supply:
> + cancel_work_sync(&priv->load_work);
> + cancel_delayed_work_sync(&priv->rcomp_work);
> + return ret;
> +}
> +
> +static int modelgauge_remove(struct i2c_client *client)
> +{
> + struct modelgauge_priv *priv = i2c_get_clientdata(client);
> +
> + cancel_work_sync(&priv->load_work);
> + cancel_delayed_work_sync(&priv->rcomp_work);
> +
> + power_supply_unregister(&priv->battery);
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int modelgauge_suspend(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct modelgauge_priv *priv = i2c_get_clientdata(client);
> + struct modelgauge_platform_data *pdata = priv->pdata;
> +
> + if (pdata && pdata->get_temperature)
> + cancel_delayed_work_sync(&priv->rcomp_work);
> +
> + switch (priv->chip) {
> + case ID_MAX17040:
> + case ID_MAX17041:
> + return 0;
> + default:
> + if (client->irq) {
> + disable_irq(client->irq);
> + enable_irq_wake(client->irq);
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int modelgauge_resume(struct device *dev)
> +{
> + struc

[PATCH v2 1/3] power_supply: modelgauge_battery: Maxim ModelGauge ICs gauge

2014-02-01 Thread Vladimir Barinov
Add Maxim ModelGauge ICs gauge driver for MAX17040/41/43/44/48/49/58/59 chips

Signed-off-by: Vladimir Barinov 

---
 drivers/power/Kconfig|9 
 drivers/power/Makefile   |1 
 drivers/power/modelgauge_battery.c   |  838 +++
 include/linux/platform_data/battery-modelgauge.h |   31 
 4 files changed, 879 insertions(+)

Index: battery-2.6/drivers/power/Kconfig
===
--- battery-2.6.orig/drivers/power/Kconfig  2014-02-02 01:29:07.434614235 
+0400
+++ battery-2.6/drivers/power/Kconfig   2014-02-02 01:29:29.070614750 +0400
@@ -205,6 +205,15 @@
  with MAX17042. This driver also supports max17047/50 chips which are
  improved version of max17042.
 
+config BATTERY_MODELGAUGE
+   tristate "Maxim ModelGauge ICs fuel gauge"
+   depends on I2C
+   select REGMAP_I2C
+   help
+ ModelGauge(TM) is a Maxim algorithm incorporated in
+ MAX17040/41/43/44/48/49/58/59 fuel-gauges for lithium-ion (Li+)
+ batteries.
+
 config BATTERY_Z2
tristate "Z2 battery driver"
depends on I2C && MACH_ZIPIT2
Index: battery-2.6/drivers/power/Makefile
===
--- battery-2.6.orig/drivers/power/Makefile 2014-02-02 01:29:07.462614237 
+0400
+++ battery-2.6/drivers/power/Makefile  2014-02-02 01:29:12.978614368 +0400
@@ -32,6 +32,7 @@
 obj-$(CONFIG_BATTERY_DA9052)   += da9052-battery.o
 obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
 obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
+obj-$(CONFIG_BATTERY_MODELGAUGE)   += modelgauge_battery.o
 obj-$(CONFIG_BATTERY_Z2)   += z2_battery.o
 obj-$(CONFIG_BATTERY_S3C_ADC)  += s3c_adc_battery.o
 obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o
Index: battery-2.6/drivers/power/modelgauge_battery.c
===
--- /dev/null   1970-01-01 00:00:00.0 +
+++ battery-2.6/drivers/power/modelgauge_battery.c  2014-02-02 
01:29:34.314614874 +0400
@@ -0,0 +1,838 @@
+/*
+ * Maxim ModelGauge ICs fuel gauge driver
+ *
+ * Author: Vladimir Barinov 
+ * Copyright (C) 2013 Cogent Embedded, Inc.
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_NAME "modelgauge"
+
+/* Register offsets for ModelGauge ICs */
+#define MODELGAUGE_VCELL_REG   0x02
+#define MODELGAUGE_SOC_REG 0x04
+#define MODELGAUGE_MODE_REG0x06
+#define MODELGAUGE_VERSION_REG 0x08
+#define MODELGAUGE_HIBRT_REG   0x0A
+#define MODELGAUGE_CONFIG_REG  0x0C
+#define MODELGAUGE_OCV_REG 0x0E
+#define MODELGAUGE_VALRT_REG   0x14
+#define MODELGAUGE_CRATE_REG   0x16
+#define MODELGAUGE_VRESETID_REG0x18
+#define MODELGAUGE_STATUS_REG  0x1A
+#define MODELGAUGE_UNLOCK_REG  0x3E
+#define MODELGAUGE_TABLE_REG   0x40
+#define MODELGAUGE_RCOMPSEG_REG0x80
+#define MODELGAUGE_CMD_REG 0xFE
+
+/* MODE register bits */
+#define MODELGAUGE_MODE_QUICKSTART (1 << 14)
+#define MODELGAUGE_MODE_ENSLEEP(1 << 13)
+#define MODELGAUGE_MODE_HIBSTAT(1 << 12)
+
+/* CONFIG register bits */
+#define MODELGAUGE_CONFIG_SLEEP(1 << 7)
+#define MODELGAUGE_CONFIG_ALSC (1 << 6)
+#define MODELGAUGE_CONFIG_ALRT (1 << 5)
+#define MODELGAUGE_CONFIG_ATHD_MASK0x1f
+
+/* STATUS register bits */
+#define MODELGAUGE_STATUS_ENVR (1 << 14)
+#define MODELGAUGE_STATUS_SC   (1 << 13)
+#define MODELGAUGE_STATUS_HD   (1 << 12)
+#define MODELGAUGE_STATUS_VR   (1 << 11)
+#define MODELGAUGE_STATUS_VL   (1 << 10)
+#define MODELGAUGE_STATUS_VH   (1 << 9)
+#define MODELGAUGE_STATUS_RI   (1 << 8)
+
+/* VRESETID register bits */
+#define MODELGAUGE_VRESETID_DIS(1 << 8)
+
+#define MODELGAUGE_UNLOCK_VALUE0x4a57
+#define MODELGAUGE_RESET_VALUE 0x5400
+
+#define MODELGAUGE_RCOMP_UPDATE_DELAY  6
+
+/* Capacity threshold where an interrupt is generated on the ALRT pin */
+#define MODELGAUGE_EMPTY_ATHD  15
+/* Enable alert for 1% soc change */
+#define MODELGAUGE_SOC_CHANGE_ALERT1
+/* Hibernate threshold (crate), where IC enters hibernate mode */
+#define MODELGAUGE_HIBRT_THD   20
+/* Active threshold (mV), where IC exits hibernate mode */
+#define MODELGAUGE_ACTIVE_THD  60
+/* Voltage (mV), when IC alerts if battery voltage less then und