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