Merge tag 'pci-v5.18-changes-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / power / supply / ug3105_battery.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Battery monitor driver for the uPI uG3105 battery monitor
4  *
5  * Note the uG3105 is not a full-featured autonomous fuel-gauge. Instead it is
6  * expected to be use in combination with some always on microcontroller reading
7  * its coulomb-counter before it can wrap (must be read every 400 seconds!).
8  *
9  * Since Linux does not monitor coulomb-counter changes while the device
10  * is off or suspended, the coulomb counter is not used atm.
11  *
12  * Possible improvements:
13  * 1. Activate commented out total_coulomb_count code
14  * 2. Reset total_coulomb_count val to 0 when the battery is as good as empty
15  *    and remember that we did this (and clear the flag for this on susp/resume)
16  * 3. When the battery is full check if the flag that we set total_coulomb_count
17  *    to when the battery was empty is set. If so we now know the capacity,
18  *    not the design, but actual capacity, of the battery
19  * 4. Add some mechanism (needs userspace help, or maybe use efivar?) to remember
20  *    the actual capacity of the battery over reboots
21  * 5. When we know the actual capacity at probe time, add energy_now and
22  *    energy_full attributes. Guess boot + resume energy_now value based on ocv
23  *    and then use total_coulomb_count to report energy_now over time, resetting
24  *    things to adjust for drift when empty/full. This should give more accurate
25  *    readings, esp. in the 30-70% range and allow userspace to estimate time
26  *    remaining till empty/full
27  * 6. Maybe unregister + reregister the psy device when we learn the actual
28  *    capacity during run-time ?
29  *
30  * The above will also require some sort of mwh_per_unit calculation. Testing
31  * has shown that an estimated 7404mWh increase of the battery's energy results
32  * in a total_coulomb_count increase of 3277 units with a 5 milli-ohm sense R.
33  *
34  * Copyright (C) 2021 Hans de Goede <hdegoede@redhat.com>
35  */
36
37 #include <linux/devm-helpers.h>
38 #include <linux/module.h>
39 #include <linux/mutex.h>
40 #include <linux/slab.h>
41 #include <linux/i2c.h>
42 #include <linux/mod_devicetable.h>
43 #include <linux/power_supply.h>
44 #include <linux/workqueue.h>
45
46 #define UG3105_MOV_AVG_WINDOW                                   8
47 #define UG3105_INIT_POLL_TIME                                   (5 * HZ)
48 #define UG3105_POLL_TIME                                        (30 * HZ)
49 #define UG3105_SETTLE_TIME                                      (1 * HZ)
50
51 #define UG3105_INIT_POLL_COUNT                                  30
52
53 #define UG3105_REG_MODE                                         0x00
54 #define UG3105_REG_CTRL1                                        0x01
55 #define UG3105_REG_COULOMB_CNT                                  0x02
56 #define UG3105_REG_BAT_VOLT                                     0x08
57 #define UG3105_REG_BAT_CURR                                     0x0c
58
59 #define UG3105_MODE_STANDBY                                     0x00
60 #define UG3105_MODE_RUN                                         0x10
61
62 #define UG3105_CTRL1_RESET_COULOMB_CNT                          0x03
63
64 #define UG3105_CURR_HYST_UA                                     65000
65
66 #define UG3105_LOW_BAT_UV                                       3700000
67 #define UG3105_FULL_BAT_HYST_UV                                 38000
68
69 struct ug3105_chip {
70         struct i2c_client *client;
71         struct power_supply *psy;
72         struct power_supply_battery_info *info;
73         struct delayed_work work;
74         struct mutex lock;
75         int ocv[UG3105_MOV_AVG_WINDOW];         /* micro-volt */
76         int intern_res[UG3105_MOV_AVG_WINDOW];  /* milli-ohm */
77         int poll_count;
78         int ocv_avg_index;
79         int ocv_avg;                            /* micro-volt */
80         int intern_res_poll_count;
81         int intern_res_avg_index;
82         int intern_res_avg;                     /* milli-ohm */
83         int volt;                               /* micro-volt */
84         int curr;                               /* micro-ampere */
85         int total_coulomb_count;
86         int uv_per_unit;
87         int ua_per_unit;
88         int status;
89         int capacity;
90         bool supplied;
91 };
92
93 static int ug3105_read_word(struct i2c_client *client, u8 reg)
94 {
95         int val;
96
97         val = i2c_smbus_read_word_data(client, reg);
98         if (val < 0)
99                 dev_err(&client->dev, "Error reading reg 0x%02x\n", reg);
100
101         return val;
102 }
103
104 static int ug3105_get_status(struct ug3105_chip *chip)
105 {
106         int full = chip->info->constant_charge_voltage_max_uv - UG3105_FULL_BAT_HYST_UV;
107
108         if (chip->curr > UG3105_CURR_HYST_UA)
109                 return POWER_SUPPLY_STATUS_CHARGING;
110
111         if (chip->curr < -UG3105_CURR_HYST_UA)
112                 return POWER_SUPPLY_STATUS_DISCHARGING;
113
114         if (chip->supplied && chip->ocv_avg > full)
115                 return POWER_SUPPLY_STATUS_FULL;
116
117         return POWER_SUPPLY_STATUS_NOT_CHARGING;
118 }
119
120 static int ug3105_get_capacity(struct ug3105_chip *chip)
121 {
122         /*
123          * OCV voltages in uV for 0-110% in 5% increments, the 100-110% is
124          * for LiPo HV (High-Voltage) bateries which can go up to 4.35V
125          * instead of the usual 4.2V.
126          */
127         static const int ocv_capacity_tbl[23] = {
128                 3350000,
129                 3610000,
130                 3690000,
131                 3710000,
132                 3730000,
133                 3750000,
134                 3770000,
135                 3786667,
136                 3803333,
137                 3820000,
138                 3836667,
139                 3853333,
140                 3870000,
141                 3907500,
142                 3945000,
143                 3982500,
144                 4020000,
145                 4075000,
146                 4110000,
147                 4150000,
148                 4200000,
149                 4250000,
150                 4300000,
151         };
152         int i, ocv_diff, ocv_step;
153
154         if (chip->ocv_avg < ocv_capacity_tbl[0])
155                 return 0;
156
157         if (chip->status == POWER_SUPPLY_STATUS_FULL)
158                 return 100;
159
160         for (i = 1; i < ARRAY_SIZE(ocv_capacity_tbl); i++) {
161                 if (chip->ocv_avg > ocv_capacity_tbl[i])
162                         continue;
163
164                 ocv_diff = ocv_capacity_tbl[i] - chip->ocv_avg;
165                 ocv_step = ocv_capacity_tbl[i] - ocv_capacity_tbl[i - 1];
166                 /* scale 0-110% down to 0-100% for LiPo HV */
167                 if (chip->info->constant_charge_voltage_max_uv >= 4300000)
168                         return (i * 500 - ocv_diff * 500 / ocv_step) / 110;
169                 else
170                         return i * 5 - ocv_diff * 5 / ocv_step;
171         }
172
173         return 100;
174 }
175
176 static void ug3105_work(struct work_struct *work)
177 {
178         struct ug3105_chip *chip = container_of(work, struct ug3105_chip,
179                                                 work.work);
180         int i, val, curr_diff, volt_diff, res, win_size;
181         bool prev_supplied = chip->supplied;
182         int prev_status = chip->status;
183         int prev_volt = chip->volt;
184         int prev_curr = chip->curr;
185         struct power_supply *psy;
186
187         mutex_lock(&chip->lock);
188
189         psy = chip->psy;
190         if (!psy)
191                 goto out;
192
193         val = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT);
194         if (val < 0)
195                 goto out;
196         chip->volt = val * chip->uv_per_unit;
197
198         val = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR);
199         if (val < 0)
200                 goto out;
201         chip->curr = (s16)val * chip->ua_per_unit;
202
203         chip->ocv[chip->ocv_avg_index] =
204                 chip->volt - chip->curr * chip->intern_res_avg / 1000;
205         chip->ocv_avg_index = (chip->ocv_avg_index + 1) % UG3105_MOV_AVG_WINDOW;
206         chip->poll_count++;
207
208         /*
209          * See possible improvements comment above.
210          *
211          * Read + reset coulomb counter every 10 polls (every 300 seconds)
212          * if ((chip->poll_count % 10) == 0) {
213          *      val = ug3105_read_word(chip->client, UG3105_REG_COULOMB_CNT);
214          *      if (val < 0)
215          *              goto out;
216          *
217          *      i2c_smbus_write_byte_data(chip->client, UG3105_REG_CTRL1,
218          *                                UG3105_CTRL1_RESET_COULOMB_CNT);
219          *
220          *      chip->total_coulomb_count += (s16)val;
221          *      dev_dbg(&chip->client->dev, "coulomb count %d total %d\n",
222          *              (s16)val, chip->total_coulomb_count);
223          * }
224          */
225
226         chip->ocv_avg = 0;
227         win_size = min(chip->poll_count, UG3105_MOV_AVG_WINDOW);
228         for (i = 0; i < win_size; i++)
229                 chip->ocv_avg += chip->ocv[i];
230         chip->ocv_avg /= win_size;
231
232         chip->supplied = power_supply_am_i_supplied(psy);
233         chip->status = ug3105_get_status(chip);
234         chip->capacity = ug3105_get_capacity(chip);
235
236         /*
237          * Skip internal resistance calc on charger [un]plug and
238          * when the battery is almost empty (voltage low).
239          */
240         if (chip->supplied != prev_supplied ||
241             chip->volt < UG3105_LOW_BAT_UV ||
242             chip->poll_count < 2)
243                 goto out;
244
245         /*
246          * Assuming that the OCV voltage does not change significantly
247          * between 2 polls, then we can calculate the internal resistance
248          * on a significant current change by attributing all voltage
249          * change between the 2 readings to the internal resistance.
250          */
251         curr_diff = abs(chip->curr - prev_curr);
252         if (curr_diff < UG3105_CURR_HYST_UA)
253                 goto out;
254
255         volt_diff = abs(chip->volt - prev_volt);
256         res = volt_diff * 1000 / curr_diff;
257
258         if ((res < (chip->intern_res_avg * 2 / 3)) ||
259             (res > (chip->intern_res_avg * 4 / 3))) {
260                 dev_dbg(&chip->client->dev, "Ignoring outlier internal resistance %d mOhm\n", res);
261                 goto out;
262         }
263
264         dev_dbg(&chip->client->dev, "Internal resistance %d mOhm\n", res);
265
266         chip->intern_res[chip->intern_res_avg_index] = res;
267         chip->intern_res_avg_index = (chip->intern_res_avg_index + 1) % UG3105_MOV_AVG_WINDOW;
268         chip->intern_res_poll_count++;
269
270         chip->intern_res_avg = 0;
271         win_size = min(chip->intern_res_poll_count, UG3105_MOV_AVG_WINDOW);
272         for (i = 0; i < win_size; i++)
273                 chip->intern_res_avg += chip->intern_res[i];
274         chip->intern_res_avg /= win_size;
275
276 out:
277         mutex_unlock(&chip->lock);
278
279         queue_delayed_work(system_wq, &chip->work,
280                            (chip->poll_count <= UG3105_INIT_POLL_COUNT) ?
281                                         UG3105_INIT_POLL_TIME : UG3105_POLL_TIME);
282
283         if (chip->status != prev_status && psy)
284                 power_supply_changed(psy);
285 }
286
287 static enum power_supply_property ug3105_battery_props[] = {
288         POWER_SUPPLY_PROP_STATUS,
289         POWER_SUPPLY_PROP_PRESENT,
290         POWER_SUPPLY_PROP_TECHNOLOGY,
291         POWER_SUPPLY_PROP_SCOPE,
292         POWER_SUPPLY_PROP_VOLTAGE_NOW,
293         POWER_SUPPLY_PROP_VOLTAGE_OCV,
294         POWER_SUPPLY_PROP_CURRENT_NOW,
295         POWER_SUPPLY_PROP_CAPACITY,
296 };
297
298 static int ug3105_get_property(struct power_supply *psy,
299                                enum power_supply_property psp,
300                                union power_supply_propval *val)
301 {
302         struct ug3105_chip *chip = power_supply_get_drvdata(psy);
303         int ret = 0;
304
305         mutex_lock(&chip->lock);
306
307         if (!chip->psy) {
308                 ret = -EAGAIN;
309                 goto out;
310         }
311
312         switch (psp) {
313         case POWER_SUPPLY_PROP_STATUS:
314                 val->intval = chip->status;
315                 break;
316         case POWER_SUPPLY_PROP_PRESENT:
317                 val->intval = 1;
318                 break;
319         case POWER_SUPPLY_PROP_TECHNOLOGY:
320                 val->intval = chip->info->technology;
321                 break;
322         case POWER_SUPPLY_PROP_SCOPE:
323                 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
324                 break;
325         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
326                 ret = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT);
327                 if (ret < 0)
328                         break;
329                 val->intval = ret * chip->uv_per_unit;
330                 ret = 0;
331                 break;
332         case POWER_SUPPLY_PROP_VOLTAGE_OCV:
333                 val->intval = chip->ocv_avg;
334                 break;
335         case POWER_SUPPLY_PROP_CURRENT_NOW:
336                 ret = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR);
337                 if (ret < 0)
338                         break;
339                 val->intval = (s16)ret * chip->ua_per_unit;
340                 ret = 0;
341                 break;
342         case POWER_SUPPLY_PROP_CAPACITY:
343                 val->intval = chip->capacity;
344                 break;
345         default:
346                 ret = -EINVAL;
347         }
348
349 out:
350         mutex_unlock(&chip->lock);
351         return ret;
352 }
353
354 static void ug3105_external_power_changed(struct power_supply *psy)
355 {
356         struct ug3105_chip *chip = power_supply_get_drvdata(psy);
357
358         dev_dbg(&chip->client->dev, "external power changed\n");
359         mod_delayed_work(system_wq, &chip->work, UG3105_SETTLE_TIME);
360 }
361
362 static const struct power_supply_desc ug3105_psy_desc = {
363         .name           = "ug3105_battery",
364         .type           = POWER_SUPPLY_TYPE_BATTERY,
365         .get_property   = ug3105_get_property,
366         .external_power_changed = ug3105_external_power_changed,
367         .properties     = ug3105_battery_props,
368         .num_properties = ARRAY_SIZE(ug3105_battery_props),
369 };
370
371 static void ug3105_init(struct ug3105_chip *chip)
372 {
373         chip->poll_count = 0;
374         chip->ocv_avg_index = 0;
375         chip->total_coulomb_count = 0;
376         i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE,
377                                   UG3105_MODE_RUN);
378         i2c_smbus_write_byte_data(chip->client, UG3105_REG_CTRL1,
379                                   UG3105_CTRL1_RESET_COULOMB_CNT);
380         queue_delayed_work(system_wq, &chip->work, 0);
381         flush_delayed_work(&chip->work);
382 }
383
384 static int ug3105_probe(struct i2c_client *client)
385 {
386         struct power_supply_config psy_cfg = {};
387         struct device *dev = &client->dev;
388         u32 curr_sense_res_uohm = 10000;
389         struct power_supply *psy;
390         struct ug3105_chip *chip;
391         int ret;
392
393         chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
394         if (!chip)
395                 return -ENOMEM;
396
397         chip->client = client;
398         mutex_init(&chip->lock);
399         ret = devm_delayed_work_autocancel(dev, &chip->work, ug3105_work);
400         if (ret)
401                 return ret;
402
403         psy_cfg.drv_data = chip;
404         psy = devm_power_supply_register(dev, &ug3105_psy_desc, &psy_cfg);
405         if (IS_ERR(psy))
406                 return PTR_ERR(psy);
407
408         ret = power_supply_get_battery_info(psy, &chip->info);
409         if (ret)
410                 return ret;
411
412         if (chip->info->factory_internal_resistance_uohm == -EINVAL ||
413             chip->info->constant_charge_voltage_max_uv == -EINVAL) {
414                 dev_err(dev, "error required properties are missing\n");
415                 return -ENODEV;
416         }
417
418         device_property_read_u32(dev, "upisemi,rsns-microohm", &curr_sense_res_uohm);
419
420         /*
421          * DAC maximum is 4.5V divided by 65536 steps + an unknown factor of 10
422          * coming from somewhere for some reason (verified with a volt-meter).
423          */
424         chip->uv_per_unit = 45000000/65536;
425         /* Datasheet says 8.1 uV per unit for the current ADC */
426         chip->ua_per_unit = 8100000 / curr_sense_res_uohm;
427
428         /* Use provided internal resistance as start point (in milli-ohm) */
429         chip->intern_res_avg = chip->info->factory_internal_resistance_uohm / 1000;
430         /* Also add it to the internal resistance moving average window */
431         chip->intern_res[0] = chip->intern_res_avg;
432         chip->intern_res_avg_index = 1;
433         chip->intern_res_poll_count = 1;
434
435         mutex_lock(&chip->lock);
436         chip->psy = psy;
437         mutex_unlock(&chip->lock);
438
439         ug3105_init(chip);
440
441         i2c_set_clientdata(client, chip);
442         return 0;
443 }
444
445 static int __maybe_unused ug3105_suspend(struct device *dev)
446 {
447         struct ug3105_chip *chip = dev_get_drvdata(dev);
448
449         cancel_delayed_work_sync(&chip->work);
450         i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE,
451                                   UG3105_MODE_STANDBY);
452
453         return 0;
454 }
455
456 static int __maybe_unused ug3105_resume(struct device *dev)
457 {
458         struct ug3105_chip *chip = dev_get_drvdata(dev);
459
460         ug3105_init(chip);
461
462         return 0;
463 }
464
465 static SIMPLE_DEV_PM_OPS(ug3105_pm_ops, ug3105_suspend,
466                         ug3105_resume);
467
468 static const struct i2c_device_id ug3105_id[] = {
469         { "ug3105" },
470         { }
471 };
472 MODULE_DEVICE_TABLE(i2c, ug3105_id);
473
474 static struct i2c_driver ug3105_i2c_driver = {
475         .driver = {
476                 .name = "ug3105",
477                 .pm = &ug3105_pm_ops,
478         },
479         .probe_new = ug3105_probe,
480         .id_table = ug3105_id,
481 };
482 module_i2c_driver(ug3105_i2c_driver);
483
484 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com");
485 MODULE_DESCRIPTION("uPI uG3105 battery monitor driver");
486 MODULE_LICENSE("GPL");