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 18 static 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 32 static 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 49 static 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 66 static 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 82 rewrite_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 111 check_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 140 lock_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!"; 189 error: 190 debug("%s: model init status: %s\n", p->name, status_msg); 191 return; 192 } 193 194 static 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 -ENODEV; 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 219 static 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 -ENODEV; 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 259 static struct power_fg power_fg_ops = { 260 .fg_battery_check = power_check_battery, 261 .fg_battery_update = power_update_battery, 262 }; 263 264 int 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