[U-Boot,09/16] pmic:fuel-gauge: Support for MAX17042 fuel-gauge

Submitted by Łukasz Majewski on Sept. 14, 2012, 3:40 p.m.

Details

Message ID 1347637215-4830-10-git-send-email-l.majewski@samsung.com
State Superseded
Delegated to: Minkyu Kang
Headers show

Commit Message

Łukasz Majewski Sept. 14, 2012, 3:40 p.m.
Support for MAX17042 fuel-gauge (FG), which is built into the MAX8997
power management device.
Special file - fg_battery_cell_params.h with cells characteristics
added.

The FG device will work with redesigned PMIC framework.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Stefano Babic <sbabic@denx.de>
---
 drivers/misc/Makefile                  |    1 +
 drivers/misc/fg_max17042.c             |  235 ++++++++++++++++++++++++++++++++
 include/power/fg_battery_cell_params.h |   88 ++++++++++++
 include/power/max17042_fg.h            |   74 ++++++++++
 include/power/power_chrg.h             |    2 +
 5 files changed, 400 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/fg_max17042.c
 create mode 100644 include/power/fg_battery_cell_params.h
 create mode 100644 include/power/max17042_fg.h

Comments

Tom Rini Sept. 14, 2012, 5:23 p.m.
On Fri, Sep 14, 2012 at 05:40:08PM +0200, Lukasz Majewski wrote:

> Support for MAX17042 fuel-gauge (FG), which is built into the MAX8997
> power management device.
> Special file - fg_battery_cell_params.h with cells characteristics
> added.
[snip]
> +#ifndef __FG_BATTERY_CELL_PARAMS_H_
> +#define __FG_BATTERY_CELL_PARAMS_H_
> +
> +#if  defined(CONFIG_POWER_FG_MAX17042) && defined(CONFIG_TRATS)
> +
> +/* Cell characteristics - Exynos4 TRATS development board */
> +
> +u16 cell_character0[16]  /* Shall be written to addr 0x80h */
> += { 0xA2A0,

This (and the rest of the file) should be:
/* Shall be written to addr 0x80h */
u16 cell_character0[16] = {
	0xA2A0,
...

Thanks.

Also:
[snip]
> +	MAX17042_AVG_CURRENT	= 0x0B,
> +	MAX17042_SOCMIX	= 0x0D,
> +	MAX17042_SOCAV		= 0x0E,

I assume this is just odd formatting in the mail and once applied it's
aligned.  If not, please fix (and check the rest of the series).
Thanks!
Lukasz Majewski Sept. 17, 2012, 8:59 p.m.
Hi Tom ,

> On Fri, Sep 14, 2012 at 05:40:08PM +0200, Lukasz Majewski wrote:
> 
> > Support for MAX17042 fuel-gauge (FG), which is built into the
> > MAX8997 power management device.
> > Special file - fg_battery_cell_params.h with cells characteristics
> > added.
> [snip]
> > +#ifndef __FG_BATTERY_CELL_PARAMS_H_
> > +#define __FG_BATTERY_CELL_PARAMS_H_
> > +
> > +#if  defined(CONFIG_POWER_FG_MAX17042) && defined(CONFIG_TRATS)
> > +
> > +/* Cell characteristics - Exynos4 TRATS development board */
> > +
> > +u16 cell_character0[16]  /* Shall be written to addr 0x80h */
> > += { 0xA2A0,
> 
> This (and the rest of the file) should be:
> /* Shall be written to addr 0x80h */
> u16 cell_character0[16] = {
> 	0xA2A0,
> ...
> 


Ok, I will fix this.
> Thanks.
> 
> Also:
> [snip]
> > +	MAX17042_AVG_CURRENT	= 0x0B,
> > +	MAX17042_SOCMIX	= 0x0D,
> > +	MAX17042_SOCAV		= 0x0E,
> 
> I assume this is just odd formatting in the mail and once applied it's
> aligned.  If not, please fix (and check the rest of the series).
> Thanks!
> 

I will double check that. Nether checkpatch nor emac's
whitespace-cleanup weren't complaining.

Regards,
Lukasz

Patch hide | download patch | download mbox

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f08a800..f3b302b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -41,6 +41,7 @@  COBJS-$(CONFIG_PMIC_I2C) += pmic_i2c.o
 COBJS-$(CONFIG_PMIC_SPI) += pmic_spi.o
 COBJS-$(CONFIG_PMIC_MAX8998) += pmic_max8998.o
 COBJS-$(CONFIG_PMIC_MAX8997) += pmic_max8997.o
+COBJS-$(CONFIG_POWER_FG_MAX17042) += fg_max17042.o
 COBJS-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/misc/fg_max17042.c b/drivers/misc/fg_max17042.c
new file mode 100644
index 0000000..27285e8
--- /dev/null
+++ b/drivers/misc/fg_max17042.c
@@ -0,0 +1,235 @@ 
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <power/pmic.h>
+#include <power/max17042_fg.h>
+#include <i2c.h>
+#include <power/max8997_pmic.h>
+#include <power/power_chrg.h>
+#include <power/fg_battery_cell_params.h>
+
+int power_fg_init(unsigned char bus)
+{
+	struct pmic *p = pmic_alloc();
+	static const char name[] = "MAX17042_FG";
+
+	debug("Board Fuel Gauge init\n");
+
+	p->name = name;
+	p->interface = PMIC_I2C;
+	p->number_of_regs = FG_NUM_OF_REGS;
+	p->hw.i2c.addr = MAX17042_I2C_ADDR;
+	p->hw.i2c.tx_num = 2;
+	p->hw.i2c.byte_order = PMIC_BYTE_ORDER_NORMAL;
+	p->bus = bus;
+
+	return 0;
+}
+
+static int fg_write_regs(struct pmic *p, u8 addr, u16 *data, int num)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < num; i++, addr++)
+		ret |= pmic_reg_write(p, addr, *(data + i));
+
+	return ret;
+}
+
+static int fg_read_regs(struct pmic *p, u8 addr, u16 *data, int num)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < num; i++, addr++)
+		ret |= pmic_reg_read(p, addr, (u32 *) (data + i));
+
+	return ret;
+}
+
+static int fg_write_and_verify(struct pmic *p, u8 addr, u16 data)
+{
+	unsigned int val = data;
+	int ret = 0;
+
+	ret |= pmic_reg_write(p, addr, val);
+	ret |= pmic_reg_read(p, addr, &val);
+
+	if (ret)
+		return ret;
+
+	if (((u16) val) == data)
+		return 0;
+
+	return -1;
+}
+
+static void por_fuelgauge_init(struct pmic *p)
+{
+	u16 r_data0[16], r_data1[16], r_data2[16];
+	u32 rewrite_count = 5, i = 0;
+	unsigned int val;
+	int ret = 0;
+
+	/* Delay 500 ms */
+	mdelay(500);
+	/* Initilize Configuration */
+	pmic_reg_write(p, MAX17042_CONFIG, 0x2310);
+
+rewrite_model:
+	/* Unlock Model Access */
+	pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
+	pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
+
+	/* Write/Read/Verify the Custom Model */
+	ret |= fg_write_regs(p, MAX17042_MODEL1, cell_character0,
+			     ARRAY_SIZE(cell_character0));
+	ret |= fg_write_regs(p, MAX17042_MODEL2, cell_character1,
+			     ARRAY_SIZE(cell_character1));
+	ret |= fg_write_regs(p, MAX17042_MODEL3, cell_character2,
+			     ARRAY_SIZE(cell_character2));
+
+	if (ret) {
+		printf("%s: Cell parameters write failed!\n", __func__);
+		return;
+	}
+
+	ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
+	ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
+	ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
+
+	if (ret)
+		printf("%s: Cell parameters read failed!\n", __func__);
+
+	for (i = 0; i < 16; i++) {
+		if ((cell_character0[i] != r_data0[i])
+		    || (cell_character1[i] != r_data1[i])
+		    || (cell_character2[i] != r_data2[i]))
+			goto rewrite_model;
+		}
+
+	/* Lock model access */
+	pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_LOCK1);
+	pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_LOCK2);
+
+	/* Verify the model access is locked */
+	ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
+	ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
+	ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
+
+	if (ret) {
+		printf("%s: Cell parameters read failed!\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(r_data0); i++) {
+		/* Check if model locked */
+		if (r_data0[i] || r_data1[i] || r_data2[i]) {
+			/* Rewrite model data - prevent from endless loop */
+			if (rewrite_count--) {
+				puts("FG - Lock model access failed!\n");
+				goto rewrite_model;
+			}
+		}
+	}
+
+	/* Write Custom Parameters */
+	fg_write_and_verify(p, MAX17042_RCOMP0, RCOMP0);
+	fg_write_and_verify(p, MAX17042_TEMPCO, TempCo);
+
+	/* Delay at least 350mS */
+	mdelay(350);
+
+	/* Initialization Complete */
+	pmic_reg_read(p, MAX17042_STATUS, &val);
+	/* Write and Verify Status with POR bit Cleared */
+	fg_write_and_verify(p, MAX17042_STATUS, val & ~MAX17042_POR);
+
+	/* Delay at least 350 ms */
+	mdelay(350);
+}
+
+int power_update_battery(struct battery *bat)
+{
+	struct pmic *p = pmic_get("MAX17042_FG");
+	unsigned int val;
+	int ret = 0;
+
+	if (pmic_probe(p)) {
+		puts("Can't find max17042 fuel gauge\n");
+		return -1;
+	}
+
+	ret |= pmic_reg_read(p, MAX17042_VFSOC, &val);
+	bat->state_of_chrg = (val >> 8);
+
+	pmic_reg_read(p, MAX17042_VCELL, &val);
+	debug("vfsoc: 0x%x\n", val);
+	bat->voltage_uV = ((val & 0xFFUL) >> 3) + ((val & 0xFF00) >> 3);
+	bat->voltage_uV = (bat->voltage_uV * 625);
+
+	pmic_reg_read(p, 0x05, &val);
+	bat->capacity = val >> 2;
+
+	return ret;
+}
+
+int power_check_battery(struct battery *bat)
+{
+	struct pmic *p = pmic_get("MAX17042_FG");
+	unsigned int val;
+	int ret = 0;
+
+	if (pmic_probe(p)) {
+		puts("Can't find max17042 fuel gauge\n");
+		return -1;
+	}
+
+	ret |= pmic_reg_read(p, MAX17042_STATUS, &val);
+	debug("fg status: 0x%x\n", val);
+
+	if (val == MAX17042_POR)
+		por_fuelgauge_init(p);
+
+	ret |= pmic_reg_read(p, MAX17042_VERSION, &val);
+	bat->version = val;
+
+	power_update_battery(bat);
+	printf("fg ver: 0x%x state_of_charge(SOC):%d%%\n",
+	       bat->version, bat->state_of_chrg);
+
+	printf("voltage:\t%d.%6.6d [V] (expected to be %d [mAh])\n",
+	       bat->voltage_uV / 1000000, bat->voltage_uV % 1000000,
+	       bat->capacity);
+
+	if (bat->voltage_uV > 3850000)
+		bat->state = EXT_SOURCE;
+	else if (bat->voltage_uV < 3600000 || bat->state_of_chrg < 5)
+		bat->state = CHARGE;
+	else
+		bat->state = NORMAL;
+
+	return ret;
+}
diff --git a/include/power/fg_battery_cell_params.h b/include/power/fg_battery_cell_params.h
new file mode 100644
index 0000000..fd068a9
--- /dev/null
+++ b/include/power/fg_battery_cell_params.h
@@ -0,0 +1,88 @@ 
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FG_BATTERY_CELL_PARAMS_H_
+#define __FG_BATTERY_CELL_PARAMS_H_
+
+#if  defined(CONFIG_POWER_FG_MAX17042) && defined(CONFIG_TRATS)
+
+/* Cell characteristics - Exynos4 TRATS development board */
+
+u16 cell_character0[16]  /* Shall be written to addr 0x80h */
+= { 0xA2A0,
+	0xB6E0,
+	0xB850,
+	0xBAD0,
+	0xBB20,
+	0xBB70,
+	0xBBC0,
+	0xBC20,
+	0xBC80,
+	0xBCE0,
+	0xBD80,
+	0xBE20,
+	0xC090,
+	0xC420,
+	0xC910,
+	0xD070
+};
+
+u16 cell_character1[16]  /* Shall be written to addr 0x90h */
+= { 0x0090,
+	0x1A50,
+	0x02F0,
+	0x2060,
+	0x2060,
+	0x2E60,
+	0x26A0,
+	0x2DB0,
+	0x2DB0,
+	0x1870,
+	0x2A20,
+	0x16F0,
+	0x08F0,
+	0x0D40,
+	0x08C0,
+	0x08C0
+};
+
+u16 cell_character2[16]  /* Shall be written to addr 0xA0h */
+= { 0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100,
+	0x0100
+};
+#endif
+#endif /* __FG_BATTERY_CELL_PARAMS_H_ */
diff --git a/include/power/max17042_fg.h b/include/power/max17042_fg.h
new file mode 100644
index 0000000..1103a48
--- /dev/null
+++ b/include/power/max17042_fg.h
@@ -0,0 +1,74 @@ 
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __MAX17042_FG_H_
+#define __MAX17042_FG_H_
+
+/* MAX 17042 registers */
+enum {
+	MAX17042_STATUS         = 0x00,
+	MAX17042_SOCREP         = 0x06,
+	MAX17042_VCELL          = 0x09,
+	MAX17042_CURRENT        = 0x0A,
+	MAX17042_AVG_CURRENT	= 0x0B,
+	MAX17042_SOCMIX	= 0x0D,
+	MAX17042_SOCAV		= 0x0E,
+	MAX17042_DESIGN_CAP	= 0x18,
+	MAX17042_AVG_VCELL	= 0x19,
+	MAX17042_CONFIG	= 0x1D,
+	MAX17042_VERSION	= 0x21,
+	MAX17042_LEARNCFG       = 0x28,
+	MAX17042_FILTERCFG	= 0x29,
+	MAX17042_RELAXCFG	= 0x2A,
+	MAX17042_MISCCFG	= 0x2B,
+	MAX17042_CGAIN		= 0x2E,
+	MAX17042_COFF		= 0x2F,
+	MAX17042_RCOMP0	= 0x38,
+	MAX17042_TEMPCO	= 0x39,
+	MAX17042_FSTAT		= 0x3D,
+	MAX17042_MLOCKReg1	= 0x62,
+	MAX17042_MLOCKReg2	= 0x63,
+	MAX17042_MODEL1         = 0x80,
+	MAX17042_MODEL2         = 0x90,
+	MAX17042_MODEL3         = 0xA0,
+	MAX17042_VFOCV		= 0xFB,
+	MAX17042_VFSOC		= 0xFF,
+
+	FG_NUM_OF_REGS = 0x100,
+};
+
+#define RCOMP0			0x0060
+#define TempCo			0x1015
+
+
+#define MAX17042_POR (1 << 1)
+
+#define MODEL_UNLOCK1		0x0059
+#define MODEL_UNLOCK2		0x00c4
+#define MODEL_LOCK1		0x0000
+#define MODEL_LOCK2		0x0000
+
+#define MAX17042_I2C_ADDR	(0x6C >> 1)
+
+int power_fg_init(unsigned char bus);
+#endif /* __MAX17042_FG_H_ */
diff --git a/include/power/power_chrg.h b/include/power/power_chrg.h
index ecbad46..c8ae650 100644
--- a/include/power/power_chrg.h
+++ b/include/power/power_chrg.h
@@ -50,5 +50,7 @@  struct battery {
 	unsigned int state;
 };
 
+int power_update_battery(struct battery *bat);
+int power_check_battery(struct battery *bat);
 int power_chrg_get_type(void);
 #endif /* __POWER_CHARGER_H_ */