Commit b95aacd332cde91299cf05e1a87dc6d7de545adb

Authored by Łukasz Majewski
Committed by Anatolij Gustschin
1 parent 294a97da34
Exists in master and in 57 other branches 8qm-imx_v2020.04_5.4.70_2.3.0, emb_lf-6.6.52-2.2.0, emb_lf_v2022.04, emb_lf_v2023.04, emb_lf_v2024.04, imx_v2015.04_4.1.15_1.0.0_ga, pitx_8mp_lf_v2020.04, smarc-8m-android-10.0.0_2.6.0, smarc-8m-android-11.0.0_2.0.0, smarc-8mp-android-11.0.0_2.0.0, smarc-emmc-imx_v2014.04_3.10.53_1.1.0_ga, smarc-emmc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx-l5.0.0_1.0.0-ga, smarc-imx6_v2018.03_4.14.98_2.0.0_ga, smarc-imx7_v2017.03_4.9.11_1.0.0_ga, smarc-imx7_v2018.03_4.14.98_2.0.0_ga, smarc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx_v2015.04_4.1.15_1.0.0_ga, smarc-imx_v2017.03_4.9.11_1.0.0_ga, smarc-imx_v2017.03_4.9.88_2.0.0_ga, smarc-imx_v2017.03_o8.1.0_1.3.0_8m, smarc-imx_v2018.03_4.14.78_1.0.0_ga, smarc-m6.0.1_2.1.0-ga, smarc-n7.1.2_2.0.0-ga, smarc-rel_imx_4.1.15_2.0.0_ga, smarc_8m-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8m-imx_v2019.04_4.19.35_1.1.0, smarc_8m_00d0-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2019.04_4.19.35_1.1.0, smarc_8mm-imx_v2020.04_5.4.24_2.1.0, smarc_8mp_lf_v2020.04, smarc_8mq-imx_v2020.04_5.4.24_2.1.0, smarc_8mq_lf_v2020.04, ti-u-boot-2015.07, u-boot-2013.01.y, v2013.10, v2013.10-smarct33, v2013.10-smartmen, v2014.01, v2014.04, v2014.04-smarct33, v2014.04-smarct33-emmc, v2014.04-smartmen, v2014.07, v2014.07-smarct33, v2014.07-smartmen, v2015.07-smarct33, v2015.07-smarct33-emmc, v2015.07-smarct4x, v2016.05-dlt, v2016.05-smarct3x, v2016.05-smarct3x-emmc, v2016.05-smarct4x, v2017.01-smarct3x, v2017.01-smarct3x-emmc, v2017.01-smarct4x

pmic:fuel-gauge: Support for MAX17042 fuel-gauge

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>

Showing 5 changed files with 462 additions and 0 deletions Side-by-side Diff

... ... @@ -294,6 +294,7 @@
294 294 LIBS-y += drivers/pci/libpci.o
295 295 LIBS-y += drivers/pcmcia/libpcmcia.o
296 296 LIBS-y += drivers/power/libpower.o \
  297 + drivers/power/fuel_gauge/libfuel_gauge.o \
297 298 drivers/power/pmic/libpmic.o \
298 299 drivers/power/battery/libbattery.o
299 300 LIBS-y += drivers/spi/libspi.o
drivers/power/fuel_gauge/Makefile
  1 +#
  2 +# Copyright (C) 2012 Samsung Electronics
  3 +# Lukasz Majewski <l.majewski@samsung.com>
  4 +#
  5 +# See file CREDITS for list of people who contributed to this
  6 +# project.
  7 +#
  8 +# This program is free software; you can redistribute it and/or
  9 +# modify it under the terms of the GNU General Public License as
  10 +# published by the Free Software Foundation; either version 2 of
  11 +# the License, or (at your option) any later version.
  12 +#
  13 +# This program is distributed in the hope that it will be useful,
  14 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 +# GNU General Public License for more details.
  17 +#
  18 +# You should have received a copy of the GNU General Public License
  19 +# along with this program; if not, write to the Free Software
  20 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 +# MA 02111-1307 USA
  22 +#
  23 +
  24 +include $(TOPDIR)/config.mk
  25 +
  26 +LIB := $(obj)libfuel_gauge.o
  27 +
  28 +COBJS-$(CONFIG_POWER_FG_MAX17042) += fg_max17042.o
  29 +
  30 +COBJS := $(COBJS-y)
  31 +SRCS := $(COBJS:.o=.c)
  32 +OBJS := $(addprefix $(obj),$(COBJS))
  33 +
  34 +all: $(LIB)
  35 +
  36 +$(LIB): $(obj).depend $(OBJS)
  37 + $(call cmd_link_o_target, $(OBJS))
  38 +
  39 +
  40 +#########################################################################
  41 +
  42 +# defines $(obj).depend target
  43 +include $(SRCTREE)/rules.mk
  44 +
  45 +sinclude $(obj).depend
  46 +
  47 +########################################################################
drivers/power/fuel_gauge/fg_max17042.c
  1 +/*
  2 + * Copyright (C) 2012 Samsung Electronics
  3 + * Lukasz Majewski <l.majewski@samsung.com>
  4 + *
  5 + * See file CREDITS for list of people who contributed to this
  6 + * project.
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License as
  10 + * published by the Free Software Foundation; either version 2 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + */
  23 +
  24 +#include <common.h>
  25 +#include <power/pmic.h>
  26 +#include <power/max17042_fg.h>
  27 +#include <i2c.h>
  28 +#include <power/max8997_pmic.h>
  29 +#include <power/power_chrg.h>
  30 +#include <power/battery.h>
  31 +#include <power/fg_battery_cell_params.h>
  32 +#include <errno.h>
  33 +
  34 +static int fg_write_regs(struct pmic *p, u8 addr, u16 *data, int num)
  35 +{
  36 + int ret = 0;
  37 + int i;
  38 +
  39 + for (i = 0; i < num; i++, addr++)
  40 + ret |= pmic_reg_write(p, addr, *(data + i));
  41 +
  42 + return ret;
  43 +}
  44 +
  45 +static int fg_read_regs(struct pmic *p, u8 addr, u16 *data, int num)
  46 +{
  47 + int ret = 0;
  48 + int i;
  49 +
  50 + for (i = 0; i < num; i++, addr++)
  51 + ret |= pmic_reg_read(p, addr, (u32 *) (data + i));
  52 +
  53 + return ret;
  54 +}
  55 +
  56 +static int fg_write_and_verify(struct pmic *p, u8 addr, u16 data)
  57 +{
  58 + unsigned int val = data;
  59 + int ret = 0;
  60 +
  61 + ret |= pmic_reg_write(p, addr, val);
  62 + ret |= pmic_reg_read(p, addr, &val);
  63 +
  64 + if (ret)
  65 + return ret;
  66 +
  67 + if (((u16) val) == data)
  68 + return 0;
  69 +
  70 + return -1;
  71 +}
  72 +
  73 +static void por_fuelgauge_init(struct pmic *p)
  74 +{
  75 + u16 r_data0[16], r_data1[16], r_data2[16];
  76 + u32 rewrite_count = 5, i = 0;
  77 + unsigned int val;
  78 + int ret = 0;
  79 +
  80 + /* Delay 500 ms */
  81 + mdelay(500);
  82 + /* Initilize Configuration */
  83 + pmic_reg_write(p, MAX17042_CONFIG, 0x2310);
  84 +
  85 +rewrite_model:
  86 + /* Unlock Model Access */
  87 + pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
  88 + pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
  89 +
  90 + /* Write/Read/Verify the Custom Model */
  91 + ret |= fg_write_regs(p, MAX17042_MODEL1, cell_character0,
  92 + ARRAY_SIZE(cell_character0));
  93 + ret |= fg_write_regs(p, MAX17042_MODEL2, cell_character1,
  94 + ARRAY_SIZE(cell_character1));
  95 + ret |= fg_write_regs(p, MAX17042_MODEL3, cell_character2,
  96 + ARRAY_SIZE(cell_character2));
  97 +
  98 + if (ret) {
  99 + printf("%s: Cell parameters write failed!\n", __func__);
  100 + return;
  101 + }
  102 +
  103 + ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
  104 + ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
  105 + ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
  106 +
  107 + if (ret)
  108 + printf("%s: Cell parameters read failed!\n", __func__);
  109 +
  110 + for (i = 0; i < 16; i++) {
  111 + if ((cell_character0[i] != r_data0[i])
  112 + || (cell_character1[i] != r_data1[i])
  113 + || (cell_character2[i] != r_data2[i]))
  114 + goto rewrite_model;
  115 + }
  116 +
  117 + /* Lock model access */
  118 + pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_LOCK1);
  119 + pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_LOCK2);
  120 +
  121 + /* Verify the model access is locked */
  122 + ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
  123 + ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
  124 + ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
  125 +
  126 + if (ret) {
  127 + printf("%s: Cell parameters read failed!\n", __func__);
  128 + return;
  129 + }
  130 +
  131 + for (i = 0; i < ARRAY_SIZE(r_data0); i++) {
  132 + /* Check if model locked */
  133 + if (r_data0[i] || r_data1[i] || r_data2[i]) {
  134 + /* Rewrite model data - prevent from endless loop */
  135 + if (rewrite_count--) {
  136 + puts("FG - Lock model access failed!\n");
  137 + goto rewrite_model;
  138 + }
  139 + }
  140 + }
  141 +
  142 + /* Write Custom Parameters */
  143 + fg_write_and_verify(p, MAX17042_RCOMP0, RCOMP0);
  144 + fg_write_and_verify(p, MAX17042_TEMPCO, TempCo);
  145 +
  146 + /* Delay at least 350mS */
  147 + mdelay(350);
  148 +
  149 + /* Initialization Complete */
  150 + pmic_reg_read(p, MAX17042_STATUS, &val);
  151 + /* Write and Verify Status with POR bit Cleared */
  152 + fg_write_and_verify(p, MAX17042_STATUS, val & ~MAX17042_POR);
  153 +
  154 + /* Delay at least 350 ms */
  155 + mdelay(350);
  156 +}
  157 +
  158 +static int power_update_battery(struct pmic *p, struct pmic *bat)
  159 +{
  160 + struct power_battery *pb = bat->pbat;
  161 + unsigned int val;
  162 + int ret = 0;
  163 +
  164 + if (pmic_probe(p)) {
  165 + puts("Can't find max17042 fuel gauge\n");
  166 + return -1;
  167 + }
  168 +
  169 + ret |= pmic_reg_read(p, MAX17042_VFSOC, &val);
  170 + pb->bat->state_of_chrg = (val >> 8);
  171 +
  172 + pmic_reg_read(p, MAX17042_VCELL, &val);
  173 + debug("vfsoc: 0x%x\n", val);
  174 + pb->bat->voltage_uV = ((val & 0xFFUL) >> 3) + ((val & 0xFF00) >> 3);
  175 + pb->bat->voltage_uV = (pb->bat->voltage_uV * 625);
  176 +
  177 + pmic_reg_read(p, 0x05, &val);
  178 + pb->bat->capacity = val >> 2;
  179 +
  180 + return ret;
  181 +}
  182 +
  183 +static int power_check_battery(struct pmic *p, struct pmic *bat)
  184 +{
  185 + struct power_battery *pb = bat->pbat;
  186 + unsigned int val;
  187 + int ret = 0;
  188 +
  189 + if (pmic_probe(p)) {
  190 + puts("Can't find max17042 fuel gauge\n");
  191 + return -1;
  192 + }
  193 +
  194 + ret |= pmic_reg_read(p, MAX17042_STATUS, &val);
  195 + debug("fg status: 0x%x\n", val);
  196 +
  197 + if (val == MAX17042_POR)
  198 + por_fuelgauge_init(p);
  199 +
  200 + ret |= pmic_reg_read(p, MAX17042_VERSION, &val);
  201 + pb->bat->version = val;
  202 +
  203 + power_update_battery(p, bat);
  204 + debug("fg ver: 0x%x\n", pb->bat->version);
  205 + printf("BAT: state_of_charge(SOC):%d%%\n",
  206 + pb->bat->state_of_chrg);
  207 +
  208 + printf(" voltage: %d.%6.6d [V] (expected to be %d [mAh])\n",
  209 + pb->bat->voltage_uV / 1000000,
  210 + pb->bat->voltage_uV % 1000000,
  211 + pb->bat->capacity);
  212 +
  213 + if (pb->bat->voltage_uV > 3850000)
  214 + pb->bat->state = EXT_SOURCE;
  215 + else if (pb->bat->voltage_uV < 3600000 || pb->bat->state_of_chrg < 5)
  216 + pb->bat->state = CHARGE;
  217 + else
  218 + pb->bat->state = NORMAL;
  219 +
  220 + return ret;
  221 +}
  222 +
  223 +static struct power_fg power_fg_ops = {
  224 + .fg_battery_check = power_check_battery,
  225 + .fg_battery_update = power_update_battery,
  226 +};
  227 +
  228 +int power_fg_init(unsigned char bus)
  229 +{
  230 + static const char name[] = "MAX17042_FG";
  231 + struct pmic *p = pmic_alloc();
  232 +
  233 + if (!p) {
  234 + printf("%s: POWER allocation error!\n", __func__);
  235 + return -ENOMEM;
  236 + }
  237 +
  238 + debug("Board Fuel Gauge init\n");
  239 +
  240 + p->name = name;
  241 + p->interface = PMIC_I2C;
  242 + p->number_of_regs = FG_NUM_OF_REGS;
  243 + p->hw.i2c.addr = MAX17042_I2C_ADDR;
  244 + p->hw.i2c.tx_num = 2;
  245 + p->sensor_byte_order = PMIC_SENSOR_BYTE_ORDER_BIG;
  246 + p->bus = bus;
  247 +
  248 + p->fg = &power_fg_ops;
  249 + return 0;
  250 +}
include/power/fg_battery_cell_params.h
  1 +/*
  2 + * Copyright (C) 2012 Samsung Electronics
  3 + * Lukasz Majewski <l.majewski@samsung.com>
  4 + *
  5 + * See file CREDITS for list of people who contributed to this
  6 + * project.
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License as
  10 + * published by the Free Software Foundation; either version 2 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + */
  23 +
  24 +#ifndef __FG_BATTERY_CELL_PARAMS_H_
  25 +#define __FG_BATTERY_CELL_PARAMS_H_
  26 +
  27 +#if defined(CONFIG_POWER_FG_MAX17042) && defined(CONFIG_TRATS)
  28 +
  29 +/* Cell characteristics - Exynos4 TRATS development board */
  30 +/* Shall be written to addr 0x80h */
  31 +u16 cell_character0[16] = {
  32 + 0xA2A0,
  33 + 0xB6E0,
  34 + 0xB850,
  35 + 0xBAD0,
  36 + 0xBB20,
  37 + 0xBB70,
  38 + 0xBBC0,
  39 + 0xBC20,
  40 + 0xBC80,
  41 + 0xBCE0,
  42 + 0xBD80,
  43 + 0xBE20,
  44 + 0xC090,
  45 + 0xC420,
  46 + 0xC910,
  47 + 0xD070
  48 +};
  49 +
  50 +/* Shall be written to addr 0x90h */
  51 +u16 cell_character1[16] = {
  52 + 0x0090,
  53 + 0x1A50,
  54 + 0x02F0,
  55 + 0x2060,
  56 + 0x2060,
  57 + 0x2E60,
  58 + 0x26A0,
  59 + 0x2DB0,
  60 + 0x2DB0,
  61 + 0x1870,
  62 + 0x2A20,
  63 + 0x16F0,
  64 + 0x08F0,
  65 + 0x0D40,
  66 + 0x08C0,
  67 + 0x08C0
  68 +};
  69 +
  70 +/* Shall be written to addr 0xA0h */
  71 +u16 cell_character2[16] = {
  72 + 0x0100,
  73 + 0x0100,
  74 + 0x0100,
  75 + 0x0100,
  76 + 0x0100,
  77 + 0x0100,
  78 + 0x0100,
  79 + 0x0100,
  80 + 0x0100,
  81 + 0x0100,
  82 + 0x0100,
  83 + 0x0100,
  84 + 0x0100,
  85 + 0x0100,
  86 + 0x0100,
  87 + 0x0100
  88 +};
  89 +#endif
  90 +#endif /* __FG_BATTERY_CELL_PARAMS_H_ */
include/power/max17042_fg.h
  1 +/*
  2 + * Copyright (C) 2012 Samsung Electronics
  3 + * Lukasz Majewski <l.majewski@samsung.com>
  4 + *
  5 + * See file CREDITS for list of people who contributed to this
  6 + * project.
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License as
  10 + * published by the Free Software Foundation; either version 2 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + */
  23 +
  24 +#ifndef __MAX17042_FG_H_
  25 +#define __MAX17042_FG_H_
  26 +
  27 +/* MAX 17042 registers */
  28 +enum {
  29 + MAX17042_STATUS = 0x00,
  30 + MAX17042_SOCREP = 0x06,
  31 + MAX17042_VCELL = 0x09,
  32 + MAX17042_CURRENT = 0x0A,
  33 + MAX17042_AVG_CURRENT = 0x0B,
  34 + MAX17042_SOCMIX = 0x0D,
  35 + MAX17042_SOCAV = 0x0E,
  36 + MAX17042_DESIGN_CAP = 0x18,
  37 + MAX17042_AVG_VCELL = 0x19,
  38 + MAX17042_CONFIG = 0x1D,
  39 + MAX17042_VERSION = 0x21,
  40 + MAX17042_LEARNCFG = 0x28,
  41 + MAX17042_FILTERCFG = 0x29,
  42 + MAX17042_RELAXCFG = 0x2A,
  43 + MAX17042_MISCCFG = 0x2B,
  44 + MAX17042_CGAIN = 0x2E,
  45 + MAX17042_COFF = 0x2F,
  46 + MAX17042_RCOMP0 = 0x38,
  47 + MAX17042_TEMPCO = 0x39,
  48 + MAX17042_FSTAT = 0x3D,
  49 + MAX17042_MLOCKReg1 = 0x62,
  50 + MAX17042_MLOCKReg2 = 0x63,
  51 + MAX17042_MODEL1 = 0x80,
  52 + MAX17042_MODEL2 = 0x90,
  53 + MAX17042_MODEL3 = 0xA0,
  54 + MAX17042_VFOCV = 0xFB,
  55 + MAX17042_VFSOC = 0xFF,
  56 +
  57 + FG_NUM_OF_REGS = 0x100,
  58 +};
  59 +
  60 +#define RCOMP0 0x0060
  61 +#define TempCo 0x1015
  62 +
  63 +
  64 +#define MAX17042_POR (1 << 1)
  65 +
  66 +#define MODEL_UNLOCK1 0x0059
  67 +#define MODEL_UNLOCK2 0x00c4
  68 +#define MODEL_LOCK1 0x0000
  69 +#define MODEL_LOCK2 0x0000
  70 +
  71 +#define MAX17042_I2C_ADDR (0x6C >> 1)
  72 +
  73 +int power_fg_init(unsigned char bus);
  74 +#endif /* __MAX17042_FG_H_ */