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