]> git.sur5r.net Git - u-boot/blob - drivers/power/fuel_gauge/fg_max17042.c
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / drivers / power / fuel_gauge / fg_max17042.c
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 }