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.majew...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: Stefano Babic <sba...@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

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.majew...@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.majew...@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.majew...@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_ */
-- 
1.7.2.3

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to