From patchwork Fri Sep 14 15:40:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?=C5=81ukasz_Majewski?= X-Patchwork-Id: 183954 X-Patchwork-Delegate: promsoft@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 98B162C00A2 for ; Sat, 15 Sep 2012 01:42:20 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 16597281D1; Fri, 14 Sep 2012 17:41:50 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id c+wU15osYGmy; Fri, 14 Sep 2012 17:41:49 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 38FC2281D7; Fri, 14 Sep 2012 17:41:18 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9AFBA281CC for ; Fri, 14 Sep 2012 17:41:15 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8-PomXiVBYVL for ; Fri, 14 Sep 2012 17:41:15 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by theia.denx.de (Postfix) with ESMTP id 75A2E281D1 for ; Fri, 14 Sep 2012 17:41:00 +0200 (CEST) Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MAC00E1UJJ9LAC0@mailout3.samsung.com> for u-boot@lists.denx.de; Sat, 15 Sep 2012 00:40:58 +0900 (KST) X-AuditID: cbfee61b-b7f826d000005fb5-2c-5053500a9220 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id DD.C8.24501.A0053505; Sat, 15 Sep 2012 00:40:58 +0900 (KST) Received: from mcdsrvbld02.digital.local ([106.116.37.23]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MAC002HNJJ64M80@mmp2.samsung.com> for u-boot@lists.denx.de; Sat, 15 Sep 2012 00:40:58 +0900 (KST) From: Lukasz Majewski To: u-boot@lists.denx.de Date: Fri, 14 Sep 2012 17:40:08 +0200 Message-id: <1347637215-4830-10-git-send-email-l.majewski@samsung.com> X-Mailer: git-send-email 1.7.10 In-reply-to: <1347637215-4830-1-git-send-email-l.majewski@samsung.com> References: <1347637215-4830-1-git-send-email-l.majewski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrMJMWRmVeSWpSXmKPExsVy+t9jQV2ugOAAg+ufuSze7u1kd2D0OHtn B2MAYxSXTUpqTmZZapG+XQJXxuZp8xgLfqdWLP/aztzAeD6wi5GTQ0LAROLKq0eMELaYxIV7 69m6GLk4hASmM0pc+LCMFcJZzCTx7ek2dpAqNgE9ic93nzKB2CICEhK/+q8yghQxC7QwSbw8 eBmsSFjAXWLC86tgRSwCqhJ31qxnBrF5BdwkVq35xQSxTl7i6f0+NhCbEyj+6XknUA0H0DZX iWOXMicw8i5gZFjFKJpakFxQnJSea6RXnJhbXJqXrpecn7uJEez1Z9I7GFc1WBxiFOBgVOLh jWANChBiTSwrrsw9xCjBwawkwmurDRTiTUmsrEotyo8vKs1JLT7EKM3BoiTOK/wpMEBIID2x JDU7NbUgtQgmy8TBKdXAGGn4bkf/mvlN1hfPZP179PbX1oCc9eetZCfqLhGW2seyY4qJ4rFe uevXk1Pymh4UhktGnG8U/jDv5URBPtkQ+7Xba+6vfTqp86HVOhPXM1OCfktmRulN6/i6b4uq hVWhVzy/t1Lj9Dn/pvzZe+7A57e3rk/2m5Gz+KkKy5GHrxvb9U6s5lit+0uJpTgj0VCLuag4 EQAFIreF9gEAAA== Cc: Lukasz Majewski , Kyungmin Park , Tom Rini Subject: [U-Boot] [PATCH 09/16] pmic:fuel-gauge: Support for MAX17042 fuel-gauge X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 Signed-off-by: Kyungmin Park Cc: Stefano Babic --- 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 + * + * 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 +#include +#include +#include +#include +#include +#include + +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 + * + * 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 + * + * 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_ */