]> git.sur5r.net Git - u-boot/blob - drivers/power/fuel_gauge/fg_max17042.c
Merge branch 'next' of git://git.denx.de/u-boot-mpc83xx
[u-boot] / drivers / power / fuel_gauge / fg_max17042.c
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
26         return ret;
27 }
28
29 static int fg_read_regs(struct pmic *p, u8 addr, u16 *data, int num)
30 {
31         int ret = 0;
32         int i;
33
34         for (i = 0; i < num; i++, addr++)
35                 ret |= pmic_reg_read(p, addr, (u32 *) (data + i));
36
37         return ret;
38 }
39
40 static int fg_write_and_verify(struct pmic *p, u8 addr, u16 data)
41 {
42         unsigned int val = data;
43         int ret = 0;
44
45         ret |= pmic_reg_write(p, addr, val);
46         ret |= pmic_reg_read(p, addr, &val);
47
48         if (ret)
49                 return ret;
50
51         if (((u16) val) == data)
52                 return 0;
53
54         return -1;
55 }
56
57 static void por_fuelgauge_init(struct pmic *p)
58 {
59         u16 r_data0[16], r_data1[16], r_data2[16];
60         u32 rewrite_count = 5, i = 0;
61         unsigned int val;
62         int ret = 0;
63
64         /* Delay 500 ms */
65         mdelay(500);
66         /* Initilize Configuration */
67         pmic_reg_write(p, MAX17042_CONFIG, 0x2310);
68
69 rewrite_model:
70         /* Unlock Model Access */
71         pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
72         pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
73
74         /* Write/Read/Verify the Custom Model */
75         ret |= fg_write_regs(p, MAX17042_MODEL1, cell_character0,
76                              ARRAY_SIZE(cell_character0));
77         ret |= fg_write_regs(p, MAX17042_MODEL2, cell_character1,
78                              ARRAY_SIZE(cell_character1));
79         ret |= fg_write_regs(p, MAX17042_MODEL3, cell_character2,
80                              ARRAY_SIZE(cell_character2));
81
82         if (ret) {
83                 printf("%s: Cell parameters write failed!\n", __func__);
84                 return;
85         }
86
87         ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
88         ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
89         ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
90
91         if (ret)
92                 printf("%s: Cell parameters read failed!\n", __func__);
93
94         for (i = 0; i < 16; i++) {
95                 if ((cell_character0[i] != r_data0[i])
96                     || (cell_character1[i] != r_data1[i])
97                     || (cell_character2[i] != r_data2[i]))
98                         goto rewrite_model;
99                 }
100
101         /* Lock model access */
102         pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_LOCK1);
103         pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_LOCK2);
104
105         /* Verify the model access is locked */
106         ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
107         ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
108         ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
109
110         if (ret) {
111                 printf("%s: Cell parameters read failed!\n", __func__);
112                 return;
113         }
114
115         for (i = 0; i < ARRAY_SIZE(r_data0); i++) {
116                 /* Check if model locked */
117                 if (r_data0[i] || r_data1[i] || r_data2[i]) {
118                         /* Rewrite model data - prevent from endless loop */
119                         if (rewrite_count--) {
120                                 puts("FG - Lock model access failed!\n");
121                                 goto rewrite_model;
122                         }
123                 }
124         }
125
126         /* Write Custom Parameters */
127         fg_write_and_verify(p, MAX17042_RCOMP0, RCOMP0);
128         fg_write_and_verify(p, MAX17042_TEMPCO, TempCo);
129
130         /* Delay at least 350mS */
131         mdelay(350);
132
133         /* Initialization Complete */
134         pmic_reg_read(p, MAX17042_STATUS, &val);
135         /* Write and Verify Status with POR bit Cleared */
136         fg_write_and_verify(p, MAX17042_STATUS, val & ~MAX17042_POR);
137
138         /* Delay at least 350 ms */
139         mdelay(350);
140 }
141
142 static int power_update_battery(struct pmic *p, struct pmic *bat)
143 {
144         struct power_battery *pb = bat->pbat;
145         unsigned int val;
146         int ret = 0;
147
148         if (pmic_probe(p)) {
149                 puts("Can't find max17042 fuel gauge\n");
150                 return -1;
151         }
152
153         ret |= pmic_reg_read(p, MAX17042_VFSOC, &val);
154         pb->bat->state_of_chrg = (val >> 8);
155
156         pmic_reg_read(p, MAX17042_VCELL, &val);
157         debug("vfsoc: 0x%x\n", val);
158         pb->bat->voltage_uV = ((val & 0xFFUL) >> 3) + ((val & 0xFF00) >> 3);
159         pb->bat->voltage_uV = (pb->bat->voltage_uV * 625);
160
161         pmic_reg_read(p, 0x05, &val);
162         pb->bat->capacity = val >> 2;
163
164         return ret;
165 }
166
167 static int power_check_battery(struct pmic *p, struct pmic *bat)
168 {
169         struct power_battery *pb = bat->pbat;
170         unsigned int val;
171         int ret = 0;
172
173         if (pmic_probe(p)) {
174                 puts("Can't find max17042 fuel gauge\n");
175                 return -1;
176         }
177
178         ret |= pmic_reg_read(p, MAX17042_STATUS, &val);
179         debug("fg status: 0x%x\n", val);
180
181         if (val == MAX17042_POR)
182                 por_fuelgauge_init(p);
183
184         ret |= pmic_reg_read(p, MAX17042_VERSION, &val);
185         pb->bat->version = val;
186
187         power_update_battery(p, bat);
188         debug("fg ver: 0x%x\n", pb->bat->version);
189         printf("BAT: state_of_charge(SOC):%d%%\n",
190                pb->bat->state_of_chrg);
191
192         printf("     voltage: %d.%6.6d [V] (expected to be %d [mAh])\n",
193                pb->bat->voltage_uV / 1000000,
194                pb->bat->voltage_uV % 1000000,
195                pb->bat->capacity);
196
197         if (pb->bat->voltage_uV > 3850000)
198                 pb->bat->state = EXT_SOURCE;
199         else if (pb->bat->voltage_uV < 3600000 || pb->bat->state_of_chrg < 5)
200                 pb->bat->state = CHARGE;
201         else
202                 pb->bat->state = NORMAL;
203
204         return ret;
205 }
206
207 static struct power_fg power_fg_ops = {
208         .fg_battery_check = power_check_battery,
209         .fg_battery_update = power_update_battery,
210 };
211
212 int power_fg_init(unsigned char bus)
213 {
214         static const char name[] = "MAX17042_FG";
215         struct pmic *p = pmic_alloc();
216
217         if (!p) {
218                 printf("%s: POWER allocation error!\n", __func__);
219                 return -ENOMEM;
220         }
221
222         debug("Board Fuel Gauge init\n");
223
224         p->name = name;
225         p->interface = PMIC_I2C;
226         p->number_of_regs = FG_NUM_OF_REGS;
227         p->hw.i2c.addr = MAX17042_I2C_ADDR;
228         p->hw.i2c.tx_num = 2;
229         p->sensor_byte_order = PMIC_SENSOR_BYTE_ORDER_BIG;
230         p->bus = bus;
231
232         p->fg = &power_fg_ops;
233         return 0;
234 }