From patchwork Fri Oct 19 15:43:59 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: 192754 X-Patchwork-Delegate: trini@ti.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 6A56E2C0093 for ; Sat, 20 Oct 2012 02:47:39 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 563E24A59E; Fri, 19 Oct 2012 17:46:47 +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 8IJ9hnomiL9G; Fri, 19 Oct 2012 17:46:47 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E25FB4A5A1; Fri, 19 Oct 2012 17:45:55 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 463C44A4B9 for ; Fri, 19 Oct 2012 17:45:52 +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 7fPmasXIGv5Q for ; Fri, 19 Oct 2012 17:45:51 +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 804604A553 for ; Fri, 19 Oct 2012 17:45:19 +0200 (CEST) Received: from epcpsbgm1.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MC500H4PD28WN00@mailout3.samsung.com> for u-boot@lists.denx.de; Sat, 20 Oct 2012 00:45:18 +0900 (KST) X-AuditID: cbfee61a-b7f976d000001eb9-e2-5081758e4a7c Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 42.E4.07865.E8571805; Sat, 20 Oct 2012 00:45:18 +0900 (KST) Received: from mcdsrvbld02.digital.local ([106.116.37.23]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MC500FFND1YC320@mmp1.samsung.com> for u-boot@lists.denx.de; Sat, 20 Oct 2012 00:45:18 +0900 (KST) From: Lukasz Majewski To: u-boot@lists.denx.de Date: Fri, 19 Oct 2012 17:43:59 +0200 Message-id: <1350661451-1273-13-git-send-email-l.majewski@samsung.com> X-Mailer: git-send-email 1.7.10 In-reply-to: <1350661451-1273-1-git-send-email-l.majewski@samsung.com> References: <1350661451-1273-1-git-send-email-l.majewski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrEJMWRmVeSWpSXmKPExsVy+t9jAd2+0sYAgwOzVC3e7u1kd2D0OHtn B2MAYxSXTUpqTmZZapG+XQJXxq/F79kL9qRXbFj5hbWBsSW4i5GTQ0LARKJp510WCFtM4sK9 9WxdjFwcQgKLGCU+bl3CCOEsZpI4vnAZI0gVm4CexOe7T5lAbBEBCYlf/VfBipgFHjBKfGla CZYQFvCSmPx/JyuIzSKgKvFt9yugOAcHr4CbxKOp/BDb5CWe3u9jAwlzAoVf/S4HCQsJuEpc aL7LMoGRdwEjwypG0dSC5ILipPRcQ73ixNzi0rx0veT83E2MYJ8/k9rBuLLB4hCjAAejEg/v r9sNAUKsiWXFlbmHGCU4mJVEeN3YGwOEeFMSK6tSi/Lji0pzUosPMUpzsCiJ8zZ7pAQICaQn lqRmp6YWpBbBZJk4OKUaGGuLvvG1qlRHPz8So+m/4Tlv97bvtrn3d2SauPklqU9hy3S1YrTo s+04sGU2j6Gp9/Qnvs/9Yw4/PTid5/1vfp3Op3mLDP+8+LpZzd9eQ2P/4S6JGKX+P9e2ruWy Fbe65famKWmC+Utpl83WonNDnx92M/c5qcvzdLfK4+4td03fLn25O/sftxJLcUaioRZzUXEi ACxN22T1AQAA Cc: Jaehoon Chung , Kyungmin Park , Tom Rini Subject: [U-Boot] [PATCH v3 12/24] 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 --- Changes for v2: - File moved to separate directory at ./drivers/power - {check|update}_battery available as callbacks from struct power_battery Changes for v3: - change code according to struct pmic redesign --- drivers/power/Makefile | 1 + drivers/power/max17042/fg_max17042.c | 244 ++++++++++++++++++++++++++++++++ include/power/fg_battery_cell_params.h | 90 ++++++++++++ include/power/max17042_fg.h | 74 ++++++++++ 4 files changed, 409 insertions(+), 0 deletions(-) create mode 100644 drivers/power/max17042/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/power/Makefile b/drivers/power/Makefile index f07644c..46989ad 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -40,6 +40,7 @@ COBJS-$(CONFIG_PMIC_MAX8998) += max8998/pmic_max8998.o COBJS-$(CONFIG_PMIC_MAX8997) += max8997/pmic_max8997.o COBJS-$(CONFIG_POWER_BATTERY_TRATS) += battery/bat_trats.o COBJS-$(CONFIG_POWER_MUIC_MAX8997) += max8997/muic_max8997.o +COBJS-$(CONFIG_POWER_FG_MAX17042) += max17042/fg_max17042.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/power/max17042/fg_max17042.c b/drivers/power/max17042/fg_max17042.c new file mode 100644 index 0000000..7366e9d --- /dev/null +++ b/drivers/power/max17042/fg_max17042.c @@ -0,0 +1,244 @@ +/* + * 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 +#include + +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); +} + +static int power_update_battery(struct pmic *p, struct pmic *bat) +{ + struct power_battery *pb = bat->pbat; + 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); + pb->bat->state_of_chrg = (val >> 8); + + pmic_reg_read(p, MAX17042_VCELL, &val); + debug("vfsoc: 0x%x\n", val); + pb->bat->voltage_uV = ((val & 0xFFUL) >> 3) + ((val & 0xFF00) >> 3); + pb->bat->voltage_uV = (pb->bat->voltage_uV * 625); + + pmic_reg_read(p, 0x05, &val); + pb->bat->capacity = val >> 2; + + return ret; +} + +static int power_check_battery(struct pmic *p, struct pmic *bat) +{ + struct power_battery *pb = bat->pbat; + 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); + pb->bat->version = val; + + power_update_battery(p, bat); + debug("fg ver: 0x%x\n", pb->bat->version); + printf("BAT: state_of_charge(SOC):%d%%\n", + pb->bat->state_of_chrg); + + printf(" voltage: %d.%6.6d [V] (expected to be %d [mAh])\n", + pb->bat->voltage_uV / 1000000, + pb->bat->voltage_uV % 1000000, + pb->bat->capacity); + + if (pb->bat->voltage_uV > 3850000) + pb->bat->state = EXT_SOURCE; + else if (pb->bat->voltage_uV < 3600000 || pb->bat->state_of_chrg < 5) + pb->bat->state = CHARGE; + else + pb->bat->state = NORMAL; + + return ret; +} + +static struct power_fg power_fg_ops = { + .fg_battery_check = power_check_battery, + .fg_battery_update = power_update_battery, +}; + +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->sensor_byte_order = PMIC_SENSOR_BYTE_ORDER_BIG; + p->bus = bus; + + p->fg = &power_fg_ops; + return 0; +} diff --git a/include/power/fg_battery_cell_params.h b/include/power/fg_battery_cell_params.h new file mode 100644 index 0000000..7ddf6f2 --- /dev/null +++ b/include/power/fg_battery_cell_params.h @@ -0,0 +1,90 @@ +/* + * 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 */ +/* Shall be written to addr 0x80h */ +u16 cell_character0[16] = { + 0xA2A0, + 0xB6E0, + 0xB850, + 0xBAD0, + 0xBB20, + 0xBB70, + 0xBBC0, + 0xBC20, + 0xBC80, + 0xBCE0, + 0xBD80, + 0xBE20, + 0xC090, + 0xC420, + 0xC910, + 0xD070 +}; + +/* Shall be written to addr 0x90h */ +u16 cell_character1[16] = { + 0x0090, + 0x1A50, + 0x02F0, + 0x2060, + 0x2060, + 0x2E60, + 0x26A0, + 0x2DB0, + 0x2DB0, + 0x1870, + 0x2A20, + 0x16F0, + 0x08F0, + 0x0D40, + 0x08C0, + 0x08C0 +}; + +/* Shall be written to addr 0xA0h */ +u16 cell_character2[16] = { + 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_ */