uboot/drivers/power/fuel_gauge/fg_max17042.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2012 Samsung Electronics
   3 *  Lukasz Majewski <l.majewski@samsung.com>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <power/pmic.h>
  10#include <power/max17042_fg.h>
  11#include <i2c.h>
  12#include <power/max8997_pmic.h>
  13#include <power/power_chrg.h>
  14#include <power/battery.h>
  15#include <power/fg_battery_cell_params.h>
  16#include <errno.h>
  17
  18static int fg_write_regs(struct pmic *p, u8 addr, u16 *data, int num)
  19{
  20        int ret = 0;
  21        int i;
  22
  23        for (i = 0; i < num; i++, addr++) {
  24                ret = pmic_reg_write(p, addr, *(data + i));
  25                if (ret)
  26                        return ret;
  27        }
  28
  29        return 0;
  30}
  31
  32static int fg_read_regs(struct pmic *p, u8 addr, u16 *data, int num)
  33{
  34        unsigned int dat;
  35        int ret = 0;
  36        int i;
  37
  38        for (i = 0; i < num; i++, addr++) {
  39                ret = pmic_reg_read(p, addr, &dat);
  40                if (ret)
  41                        return ret;
  42
  43                *(data + i) = (u16)dat;
  44        }
  45
  46        return 0;
  47}
  48
  49static int fg_write_and_verify(struct pmic *p, u8 addr, u16 data)
  50{
  51        unsigned int val = data;
  52        int ret = 0;
  53
  54        ret |= pmic_reg_write(p, addr, val);
  55        ret |= pmic_reg_read(p, addr, &val);
  56
  57        if (ret)
  58                return ret;
  59
  60        if (((u16) val) == data)
  61                return 0;
  62
  63        return -1;
  64}
  65
  66static void por_fuelgauge_init(struct pmic *p)
  67{
  68        u16 r_data0[16], r_data1[16], r_data2[16];
  69        u32 rewrite_count = 5;
  70        u32 check_count;
  71        u32 lock_count;
  72        u32 i = 0;
  73        u32 val;
  74        s32 ret = 0;
  75        char *status_msg;
  76
  77        /* Delay 500 ms */
  78        mdelay(500);
  79        /* Initilize Configuration */
  80        pmic_reg_write(p, MAX17042_CONFIG, 0x2310);
  81
  82rewrite_model:
  83        check_count = 5;
  84        lock_count = 5;
  85
  86        if (!rewrite_count--) {
  87                status_msg = "init failed!";
  88                goto error;
  89        }
  90
  91        /* Unlock Model Access */
  92        pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
  93        pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
  94
  95        /* Write/Read/Verify the Custom Model */
  96        ret = fg_write_regs(p, MAX17042_MODEL1, cell_character0,
  97                             ARRAY_SIZE(cell_character0));
  98        if (ret)
  99                goto rewrite_model;
 100
 101        ret = fg_write_regs(p, MAX17042_MODEL2, cell_character1,
 102                             ARRAY_SIZE(cell_character1));
 103        if (ret)
 104                goto rewrite_model;
 105
 106        ret = fg_write_regs(p, MAX17042_MODEL3, cell_character2,
 107                             ARRAY_SIZE(cell_character2));
 108        if (ret)
 109                goto rewrite_model;
 110
 111check_model:
 112        if (!check_count--) {
 113                if (rewrite_count)
 114                        goto rewrite_model;
 115                else
 116                        status_msg = "check failed!";
 117
 118                goto error;
 119        }
 120
 121        ret = fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
 122        if (ret)
 123                goto check_model;
 124
 125        ret = fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
 126        if (ret)
 127                goto check_model;
 128
 129        ret = fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
 130        if (ret)
 131                goto check_model;
 132
 133        for (i = 0; i < 16; i++) {
 134                if ((cell_character0[i] != r_data0[i])
 135                    || (cell_character1[i] != r_data1[i])
 136                    || (cell_character2[i] != r_data2[i]))
 137                        goto rewrite_model;
 138                }
 139
 140lock_model:
 141        if (!lock_count--) {
 142                if (rewrite_count)
 143                        goto rewrite_model;
 144                else
 145                        status_msg = "lock failed!";
 146
 147                goto error;
 148        }
 149
 150        /* Lock model access */
 151        pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_LOCK1);
 152        pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_LOCK2);
 153
 154        /* Verify the model access is locked */
 155        ret = fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
 156        if (ret)
 157                goto lock_model;
 158
 159        ret = fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
 160        if (ret)
 161                goto lock_model;
 162
 163        ret = fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
 164        if (ret)
 165                goto lock_model;
 166
 167        for (i = 0; i < ARRAY_SIZE(r_data0); i++) {
 168                /* Check if model locked */
 169                if (r_data0[i] || r_data1[i] || r_data2[i])
 170                        goto lock_model;
 171        }
 172
 173        /* Write Custom Parameters */
 174        fg_write_and_verify(p, MAX17042_RCOMP0, RCOMP0);
 175        fg_write_and_verify(p, MAX17042_TEMPCO, TempCo);
 176
 177        /* Delay at least 350mS */
 178        mdelay(350);
 179
 180        /* Initialization Complete */
 181        pmic_reg_read(p, MAX17042_STATUS, &val);
 182        /* Write and Verify Status with POR bit Cleared */
 183        fg_write_and_verify(p, MAX17042_STATUS, val & ~MAX17042_POR);
 184
 185        /* Delay at least 350 ms */
 186        mdelay(350);
 187
 188        status_msg = "OK!";
 189error:
 190        debug("%s: model init status: %s\n", p->name, status_msg);
 191        return;
 192}
 193
 194static int power_update_battery(struct pmic *p, struct pmic *bat)
 195{
 196        struct power_battery *pb = bat->pbat;
 197        unsigned int val;
 198        int ret = 0;
 199
 200        if (pmic_probe(p)) {
 201                puts("Can't find max17042 fuel gauge\n");
 202                return -1;
 203        }
 204
 205        ret |= pmic_reg_read(p, MAX17042_VFSOC, &val);
 206        pb->bat->state_of_chrg = (val >> 8);
 207
 208        pmic_reg_read(p, MAX17042_VCELL, &val);
 209        debug("vfsoc: 0x%x\n", val);
 210        pb->bat->voltage_uV = ((val & 0xFFUL) >> 3) + ((val & 0xFF00) >> 3);
 211        pb->bat->voltage_uV = (pb->bat->voltage_uV * 625);
 212
 213        pmic_reg_read(p, 0x05, &val);
 214        pb->bat->capacity = val >> 2;
 215
 216        return ret;
 217}
 218
 219static int power_check_battery(struct pmic *p, struct pmic *bat)
 220{
 221        struct power_battery *pb = bat->pbat;
 222        unsigned int val;
 223        int ret = 0;
 224
 225        if (pmic_probe(p)) {
 226                puts("Can't find max17042 fuel gauge\n");
 227                return -1;
 228        }
 229
 230        ret |= pmic_reg_read(p, MAX17042_STATUS, &val);
 231        debug("fg status: 0x%x\n", val);
 232
 233        if (val & MAX17042_POR)
 234                por_fuelgauge_init(p);
 235
 236        ret |= pmic_reg_read(p, MAX17042_VERSION, &val);
 237        pb->bat->version = val;
 238
 239        power_update_battery(p, bat);
 240        debug("fg ver: 0x%x\n", pb->bat->version);
 241        printf("BAT: state_of_charge(SOC):%d%%\n",
 242               pb->bat->state_of_chrg);
 243
 244        printf("     voltage: %d.%6.6d [V] (expected to be %d [mAh])\n",
 245               pb->bat->voltage_uV / 1000000,
 246               pb->bat->voltage_uV % 1000000,
 247               pb->bat->capacity);
 248
 249        if (pb->bat->voltage_uV > 3850000)
 250                pb->bat->state = EXT_SOURCE;
 251        else if (pb->bat->voltage_uV < 3600000 || pb->bat->state_of_chrg < 5)
 252                pb->bat->state = CHARGE;
 253        else
 254                pb->bat->state = NORMAL;
 255
 256        return ret;
 257}
 258
 259static struct power_fg power_fg_ops = {
 260        .fg_battery_check = power_check_battery,
 261        .fg_battery_update = power_update_battery,
 262};
 263
 264int power_fg_init(unsigned char bus)
 265{
 266        static const char name[] = "MAX17042_FG";
 267        struct pmic *p = pmic_alloc();
 268
 269        if (!p) {
 270                printf("%s: POWER allocation error!\n", __func__);
 271                return -ENOMEM;
 272        }
 273
 274        debug("Board Fuel Gauge init\n");
 275
 276        p->name = name;
 277        p->interface = PMIC_I2C;
 278        p->number_of_regs = FG_NUM_OF_REGS;
 279        p->hw.i2c.addr = MAX17042_I2C_ADDR;
 280        p->hw.i2c.tx_num = 2;
 281        p->sensor_byte_order = PMIC_SENSOR_BYTE_ORDER_BIG;
 282        p->bus = bus;
 283
 284        p->fg = &power_fg_ops;
 285        return 0;
 286}
 287