blob: 0a5bcfe98e279c2ac151a8199ef7c6121c0e3897 [file] [log] [blame]
Ken Tsou8acade12020-07-09 03:17:35 +08001/*
2 * Fuel gauge driver for Maxim 17201/17205
3 *
4 * Copyright (C) 2018 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#define pr_fmt(fmt) KBUILD_MODNAME ": %s " fmt, __func__
18
19#include <linux/err.h>
20#include <linux/i2c.h>
21#include <linux/iio/consumer.h>
22#include <linux/interrupt.h>
23#include <linux/module.h>
24#include <linux/of.h>
25#include <linux/of_gpio.h>
26#include <linux/pm_runtime.h>
Ken Tsou8acade12020-07-09 03:17:35 +080027#include <linux/regmap.h>
28#include <linux/slab.h>
29#include <linux/time.h>
30
31#include <linux/cdev.h>
32#include <linux/device.h>
33#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
34#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */
AleX Pelosi856679c2020-09-01 13:47:28 -070035#include "gbms_power_supply.h"
Ken Tsou98b71642020-07-09 16:17:29 +080036#include "google_bms.h"
Ken Tsou98b71642020-07-09 16:17:29 +080037#include "max1720x_battery.h"
Ken Tsou8acade12020-07-09 03:17:35 +080038
39#include <linux/debugfs.h>
40
41#define MAX17X0X_TPOR_MS 150
42
43#define MAX1720X_TRECALL_MS 5
44#define MAX1730X_TRECALL_MS 5
45#define MAX1720X_TICLR_MS 500
46#define MAX1720X_I2C_DRIVER_NAME "max_fg_irq"
47#define MAX1720X_DELAY_INIT_MS 1000
48#define FULLCAPNOM_STABILIZE_CYCLES 5
49#define CYCLE_BUCKET_SIZE 200
50#define TEMP_BUCKET_SIZE 5 /* unit is 0.1 degree C */
51#define NB_CYCLE_BUCKETS 4
52
AleX Pelosi9f326fb2020-10-27 01:50:47 -070053/* capacity drift */
54#define BATTERY_DEFAULT_CYCLE_STABLE 0
55#define BATTERY_DEFAULT_CYCLE_FADE 0
56#define BATTERY_DEFAULT_CYCLE_BAND 10
57#define BATTERY_MAX_CYCLE_BAND 20
58
Ken Tsou8acade12020-07-09 03:17:35 +080059#define HISTORY_DEVICENAME "maxfg_history"
60
Jenny Ho80a583b2021-11-15 01:46:25 +080061#define FILTERCFG_TEMP_HYSTERESIS 30
62
Jack Wuecfe7562022-03-17 18:17:53 +080063#define BHI_IMPEDANCE_SOC_LO 50
64#define BHI_IMPEDANCE_SOC_HI 55
65#define BHI_IMPEDANCE_TEMP_LO 250
66#define BHI_IMPEDANCE_TEMP_HI 300
AleX Pelosi43986542022-05-03 15:33:18 -070067#define BHI_IMPEDANCE_CYCLE_CNT 5
Jack Wuecfe7562022-03-17 18:17:53 +080068#define BHI_IMPEDANCE_TIMERH 50 /* 7*24 / 3.2hr */
69
Ken Tsou98b71642020-07-09 16:17:29 +080070#include "max1720x.h"
71#include "max1730x.h"
72#include "max_m5.h"
Ken Tsou8acade12020-07-09 03:17:35 +080073
74enum max17xxx_register {
75 MAX17XXX_COMMAND = MAX1720X_COMMAND,
76};
77
78enum max17xxx_nvram {
79 MAX17XXX_QHCA = MAX1720X_NUSER18C,
80 MAX17XXX_QHQH = MAX1720X_NUSER18D,
81};
82
83enum max17xxx_command_bits {
Thierry Strudel4ab0fcb2021-02-02 10:31:46 -080084 MAX17XXX_COMMAND_NV_RECALL = 0xE001,
Ken Tsou8acade12020-07-09 03:17:35 +080085};
86
87/* Capacity Estimation */
88struct gbatt_capacity_estimation {
89 const struct max17x0x_reg *bcea;
90 struct mutex batt_ce_lock;
91 struct delayed_work settle_timer;
92 int cap_tsettle;
93 int cap_filt_length;
94 int estimate_state;
95 bool cable_in;
96 int delta_cc_sum;
97 int delta_vfsoc_sum;
98 int cap_filter_count;
99 int start_cc;
100 int start_vfsoc;
101};
102
Jenny Ho39b2def2022-03-02 18:18:13 +0800103struct max1720x_rc_switch {
104 struct delayed_work switch_work;
105 bool available;
106 bool enable;
107 int soc;
108 int temp;
109 u16 rc1_tempco;
110 u16 rc2_tempco;
111 u16 rc2_learncfg;
112};
113
Jenny Ho316abea2021-06-22 17:38:27 +0800114#define DEFAULT_BATTERY_ID 0
Ken Tsou8acade12020-07-09 03:17:35 +0800115#define DEFAULT_BATTERY_ID_RETRIES 5
116
117#define DEFAULT_CAP_SETTLE_INTERVAL 3
118#define DEFAULT_CAP_FILTER_LENGTH 12
119
120#define ESTIMATE_DONE 2
121#define ESTIMATE_PENDING 1
122#define ESTIMATE_NONE 0
123
124#define CE_CAP_FILTER_COUNT 0
125#define CE_DELTA_CC_SUM_REG 1
126#define CE_DELTA_VFSOC_SUM_REG 2
127
128#define CE_FILTER_COUNT_MAX 15
129
AleX Pelosi9e8633f2022-05-06 18:21:12 +0000130#define BHI_CAP_FCN_COUNT 3
131
132#pragma pack(1)
133struct max17x0x_eeprom_history {
134 u16 tempco;
135 u16 rcomp0;
136 u8 timerh;
137 unsigned fullcapnom:10;
138 unsigned fullcaprep:10;
139 unsigned mixsoc:6;
140 unsigned vfsoc:6;
141 unsigned maxvolt:4;
142 unsigned minvolt:4;
143 unsigned maxtemp:4;
144 unsigned mintemp:4;
145 unsigned maxchgcurr:4;
146 unsigned maxdischgcurr:4;
147};
148#pragma pack()
149
Ken Tsou8acade12020-07-09 03:17:35 +0800150
151struct max1720x_history {
152 int page_size;
153
154 loff_t history_index;
155 int history_count;
156 bool *page_status;
157 u16 *history;
158};
159
Ken Tsou8acade12020-07-09 03:17:35 +0800160struct max1720x_chip {
161 struct device *dev;
162 bool irq_shared;
163 struct i2c_client *primary;
164 struct i2c_client *secondary;
165
166 int gauge_type; /* -1 not present, 0=max1720x, 1=max1730x */
167 struct max17x0x_regmap regmap;
168 struct max17x0x_regmap regmap_nvram;
169
170 struct power_supply *psy;
171 struct delayed_work init_work;
172 struct device_node *batt_node;
173
174 u16 devname;
175 struct max17x0x_cache_data nRAM_por;
176 bool needs_reset;
177 int (*fixups_fn)(struct max1720x_chip *chip);
178
179 /* config */
180 void *model_data;
181 struct mutex model_lock;
182 struct delayed_work model_work;
AleX Pelosi7f421272020-12-07 11:24:11 -0800183 int model_next_update;
Ken Tsou8acade12020-07-09 03:17:35 +0800184 /* also used to restore model state from permanent storage */
185 u16 reg_prop_capacity_raw;
AleX Pelosi7f421272020-12-07 11:24:11 -0800186 bool model_state_valid; /* state read from persistent */
Ken Tsou8acade12020-07-09 03:17:35 +0800187 int model_reload;
AleX Pelosi7f421272020-12-07 11:24:11 -0800188 bool model_ok; /* model is running */
Ken Tsou8acade12020-07-09 03:17:35 +0800189
190 /* history */
191 struct mutex history_lock;
192 int hcmajor;
193 struct cdev hcdev;
194 struct class *hcclass;
195 bool history_available;
196 bool history_added;
197 int history_page_size;
198 int nb_history_pages;
199 int nb_history_flag_reg;
200
AleX Pelosi8c5fa772020-10-03 13:36:56 -0700201 int fake_battery;
Ken Tsou8acade12020-07-09 03:17:35 +0800202 /* for storage interface */
203 struct max1720x_history history_storage;
204
205 u16 RSense;
206 u16 RConfig;
207
208 int batt_id;
209 int batt_id_defer_cnt;
210 int cycle_count;
Jenny Hof5be5122021-01-08 18:43:45 +0800211 int cycle_count_offset;
Jenny Ho70c3d772021-03-12 17:49:43 +0800212 u16 eeprom_cycle;
Ken Tsou8acade12020-07-09 03:17:35 +0800213
214 bool init_complete;
215 bool resume_complete;
Wasb Liudc49a932022-03-01 14:44:17 +0800216 bool irq_disabled;
Ken Tsou8acade12020-07-09 03:17:35 +0800217 u16 health_status;
218 int fake_capacity;
219 int previous_qh;
220 int current_capacity;
221 int prev_charge_status;
Jenny Ho55836002020-11-06 14:41:18 +0800222 char serial_number[30];
Ken Tsou8acade12020-07-09 03:17:35 +0800223 bool offmode_charger;
224 s32 convgcfg_hysteresis;
225 int nb_convgcfg;
226 int curr_convgcfg_idx;
227 s16 *temp_convgcfg;
228 u16 *convgcfg_values;
229 struct mutex convgcfg_lock;
Jenny Ho80a583b2021-11-15 01:46:25 +0800230 struct max1720x_dyn_filtercfg dyn_filtercfg;
Ken Tsou8acade12020-07-09 03:17:35 +0800231 bool shadow_override;
232 int nb_empty_voltage;
233 u16 *empty_voltage;
Jenny Hod4721532021-08-12 12:29:25 +0800234 bool por;
Ken Tsou8acade12020-07-09 03:17:35 +0800235
236 unsigned int debug_irq_none_cnt;
237 unsigned long icnt;
238 int zero_irq;
239
AleX Pelosi9f326fb2020-10-27 01:50:47 -0700240 /* fix capacity drift */
241 struct max1720x_drift_data drift_data;
242 int comp_update_count;
243 int dxacc_update_count;
Ken Tsou8acade12020-07-09 03:17:35 +0800244
245 /* Capacity Estimation */
246 struct gbatt_capacity_estimation cap_estimate;
247 struct logbuffer *ce_log;
AleX Pelosi45558f82021-01-12 00:34:09 -0800248
249 /* debug interface, register to read or write */
250 u32 debug_reg_address;
Jenny Ho36b6c9f2020-12-21 09:57:16 +0800251
Jenny Ho5381a6f2021-08-11 14:34:45 +0800252 /* dump data to logbuffer periodically */
253 struct logbuffer *monitor_log;
254 u16 pre_repsoc;
255
Jenny Ho36b6c9f2020-12-21 09:57:16 +0800256 struct power_supply_desc max1720x_psy_desc;
Jack Wuecfe7562022-03-17 18:17:53 +0800257
AleX Pelosi9e8633f2022-05-06 18:21:12 +0000258 int bhi_fcn_count;
Jack Wu94fd2c72022-03-29 20:44:19 +0800259 int bhi_acim;
AleX Pelosi9e8633f2022-05-06 18:21:12 +0000260
Jenny Ho39b2def2022-03-02 18:18:13 +0800261 struct max1720x_rc_switch rc_switch;
Ken Tsou8acade12020-07-09 03:17:35 +0800262};
263
264#define MAX1720_EMPTY_VOLTAGE(profile, temp, cycle) \
265 profile->empty_voltage[temp * NB_CYCLE_BUCKETS + cycle]
266
Jenny Ho7c84e052021-07-09 17:43:33 +0800267
Jenny Hod4721532021-08-12 12:29:25 +0800268static irqreturn_t max1720x_fg_irq_thread_fn(int irq, void *obj);
Jenny Ho062fe712022-10-03 15:06:39 +0800269static int max1720x_set_next_update(struct max1720x_chip *chip);
Ken Tsou8acade12020-07-09 03:17:35 +0800270
271static bool max17x0x_reglog_init(struct max1720x_chip *chip)
272{
273 chip->regmap.reglog =
274 devm_kzalloc(chip->dev, sizeof(*chip->regmap.reglog),
275 GFP_KERNEL);
276 chip->regmap_nvram.reglog =
277 devm_kzalloc(chip->dev, sizeof(*chip->regmap.reglog),
278 GFP_KERNEL);
279
280 return chip->regmap.reglog && chip->regmap_nvram.reglog;
281}
282
283/* ------------------------------------------------------------------------- */
284
285
286/* TODO: split between NV and Volatile? */
287
288
AleX Pelosi76a3e5b2022-01-06 13:57:18 -0800289static const struct max17x0x_reg * max17x0x_find_by_index(struct max17x0x_regtags *tags,
290 int index)
Ken Tsou8acade12020-07-09 03:17:35 +0800291{
292 if (index < 0 || !tags || index >= tags->max)
293 return NULL;
294
295 return &tags->map[index];
296}
297
AleX Pelosi76a3e5b2022-01-06 13:57:18 -0800298static const struct max17x0x_reg * max17x0x_find_by_tag(struct max17x0x_regmap *map,
299 enum max17x0x_reg_tags tag)
Ken Tsou8acade12020-07-09 03:17:35 +0800300{
301 return max17x0x_find_by_index(&map->regtags, tag);
302}
303
304static inline int max17x0x_reg_read(struct max17x0x_regmap *map,
305 enum max17x0x_reg_tags tag,
306 u16 *val)
307{
308 const struct max17x0x_reg *reg;
309 unsigned int tmp;
310 int rtn;
311
312 reg = max17x0x_find_by_tag(map, tag);
313 if (!reg)
314 return -EINVAL;
315
316 rtn = regmap_read(map->regmap, reg->reg, &tmp);
317 if (rtn)
318 pr_err("Failed to read %x\n", reg->reg);
319 else
320 *val = tmp;
321
322 return rtn;
323}
324
325/* ------------------------------------------------------------------------- */
326
327/*
328 * offset of the register in this atom.
329 * NOTE: this is the byte offset regardless of the size of the register
330 */
331static int max17x0x_reg_offset_of(const struct max17x0x_reg *a,
332 unsigned int reg)
333{
334 int i;
335
336 switch (a->type) {
337 case GBMS_ATOM_TYPE_REG:
338 return (reg == a->reg) ? 0 : -EINVAL;
339 case GBMS_ATOM_TYPE_ZONE:
340 if (reg >= a->base && reg < a->base + a->size)
341 return (reg - a->base) * 2;
342 break;
343 case GBMS_ATOM_TYPE_MAP:
344 for (i = 0 ; i < a->size ; i++)
345 if (a->map[i] == reg)
346 return i * 2;
347 break;
348 }
349
350 return -ERANGE;
351}
352
353static int max17x0x_reg_store_sz(struct max17x0x_regmap *map,
354 const struct max17x0x_reg *a,
355 const void *data,
356 int size)
357{
358 int i, ret;
359
360 if (size > a->size)
361 size = a->size;
362
363 if (a->type == GBMS_ATOM_TYPE_MAP) {
364 const u16 *b = (u16 *)data;
365
366 if (size % 2)
367 return -ERANGE;
368
369 for (i = 0; i < size / 2 ; i++) {
370 ret = regmap_write(map->regmap, a->map[i], b[i]);
371 if (ret < 0)
372 break;
373
374 max17x0x_reglog_log(map->reglog, a->map[i], b[i], ret);
375 }
376 } else if (a->type == GBMS_ATOM_TYPE_SET) {
377 ret = -EINVAL;
378 } else {
379 ret = regmap_raw_write(map->regmap, a->base, data, size);
380
381 if (map->reglog) {
382 const u16 *b = (u16 *)data;
383
384 for (i = 0; i < size ; i += 2)
385 max17x0x_reglog_log(map->reglog, a->base + i,
386 b[i], ret);
387 }
388 }
389
390 return ret;
391}
392
393static int max17x0x_reg_load_sz(struct max17x0x_regmap *map,
394 const struct max17x0x_reg *a,
395 void *data,
396 int size)
397{
398 int ret;
399
400 if (size > a->size)
401 size = a->size;
402
403 if (a->type == GBMS_ATOM_TYPE_MAP) {
404 int i;
405 unsigned int tmp;
406 u16 *b = (u16 *)data;
407
408 if (size % 2)
409 return -ERANGE;
410
411 for (i = 0; i < size / 2 ; i++) {
412 ret = regmap_read(map->regmap,
413 (unsigned int)a->map[i],
414 &tmp);
415 if (ret < 0)
416 break;
417 b[i] = tmp;
418 }
419 } else if (a->type == GBMS_ATOM_TYPE_SET) {
420 ret = -EINVAL;
421 } else {
422 ret = regmap_raw_read(map->regmap, a->base, data, size);
423 }
424
425 return ret;
426}
427
428#define max17x0x_reg_store(map, a, data) \
429 max17x0x_reg_store_sz(map, a, data, (a)->size)
430
431#define max17x0x_reg_load(map, a, data) \
432 max17x0x_reg_load_sz(map, a, data, (a)->size)
433
434
435static u16 *batt_alloc_array(int count, int size)
436{
437 return (u16 *)kmalloc_array(count, size, GFP_KERNEL);
438}
439
440/* CACHE ----------------------------------------------------------------- */
441
442static int max17x0x_cache_index_of(const struct max17x0x_cache_data *cache,
443 unsigned int reg)
444{
445 const int offset = max17x0x_reg_offset_of(&cache->atom, reg);
446
447 return (offset < 0) ? offset : offset / 2;
448}
449
450#define max17x0x_cache_store(cache, regmap) \
451 max17x0x_reg_store(regmap, &(cache)->atom, (cache)->cache_data)
452
453#define max17x0x_cache_load(cache, regmap) \
454 max17x0x_reg_load(regmap, &(cache)->atom, (cache)->cache_data)
455
456#define max17x0x_cache_memcmp(src, dst) \
457 memcmp((src)->cache_data, (dst)->cache_data, (src)->atom.size)
458
459static void max17x0x_cache_free(struct max17x0x_cache_data *cache)
460{
461 kfree(cache->cache_data);
462 cache->cache_data = NULL;
463}
464
465static int max17x0x_cache_dup(struct max17x0x_cache_data *dst,
466 const struct max17x0x_cache_data *src)
467{
468 memcpy(dst, src, sizeof(*dst));
469
470 dst->cache_data = (u16 *)kmalloc(src->atom.size, GFP_KERNEL);
471 if (!dst->cache_data)
472 return -ENOMEM;
473
474 memcpy(dst->cache_data, src->cache_data, src->atom.size);
475 return 0;
476}
477
478static int max17x0x_cache_init(struct max17x0x_cache_data *cache,
479 u16 start, int end)
480{
481 const int count = end - start + 1; /* includes end */
482
483 memset(cache, 0, sizeof(*cache));
484
485 cache->cache_data = batt_alloc_array(count, sizeof(u16));
486 if (!cache->cache_data)
487 return -ENOMEM;
488
489 cache->atom.type = GBMS_ATOM_TYPE_ZONE;
490 cache->atom.size = count * sizeof(u16);
491 cache->atom.base = start;
492
493 return 0;
494}
495
496static int max17x0x_nvram_cache_init(struct max17x0x_cache_data *cache,
497 int gauge_type)
498{
499 int ret;
500
501 if (gauge_type == MAX1730X_GAUGE_TYPE) {
502 ret = max17x0x_cache_init(cache,
503 MAX1730X_NVRAM_START,
504 MAX1730X_NVRAM_END);
505 } else {
506 ret = max17x0x_cache_init(cache,
507 MAX1720X_NVRAM_START,
508 MAX1720X_NVRAM_END);
509 }
510
511 return ret;
512}
513
514/* ------------------------------------------------------------------------- */
515
516static inline int reg_to_percentage(u16 val)
517{
518 /* LSB: 1/256% */
519 return val >> 8;
520}
521
522static inline int reg_to_twos_comp_int(u16 val)
523{
524 /* Convert u16 to twos complement */
525 return -(val & 0x8000) + (val & 0x7FFF);
526}
527
528static inline int reg_to_micro_amp(s16 val, u16 rsense)
529{
530 /* LSB: 1.5625μV/RSENSE ; Rsense LSB is 10μΩ */
531 return div_s64((s64) val * 156250, rsense);
532}
533
534static inline int reg_to_deci_deg_cel(s16 val)
535{
536 /* LSB: 1/256°C */
537 return div_s64((s64) val * 10, 256);
538}
539
540static inline int reg_to_resistance_micro_ohms(s16 val, u16 rsense)
541{
542 /* LSB: 1/4096 Ohm */
543 return div_s64((s64) val * 1000 * rsense, 4096);
544}
545
George Lee014b6742021-05-17 11:25:22 -0700546static inline int reg_to_cycles(u32 val, int gauge_type)
Ken Tsou8acade12020-07-09 03:17:35 +0800547{
Jenny Ho263f1452020-10-30 02:56:17 +0800548 if (gauge_type == MAX_M5_GAUGE_TYPE) {
549 /* LSB: 1% of one cycle */
George Lee014b6742021-05-17 11:25:22 -0700550 return DIV_ROUND_CLOSEST(val, 100);
Jenny Ho263f1452020-10-30 02:56:17 +0800551 } else {
552 /* LSB: 16% of one cycle */
George Lee014b6742021-05-17 11:25:22 -0700553 return DIV_ROUND_CLOSEST(val * 16, 100);
Jenny Ho263f1452020-10-30 02:56:17 +0800554 }
Ken Tsou8acade12020-07-09 03:17:35 +0800555}
556
557static inline int reg_to_seconds(s16 val)
558{
559 /* LSB: 5.625 seconds */
560 return DIV_ROUND_CLOSEST((int) val * 5625, 1000);
561}
562
563static inline int reg_to_vempty(u16 val)
564{
565 return ((val >> 7) & 0x1FF) * 10;
566}
567
568static inline int reg_to_vrecovery(u16 val)
569{
570 return (val & 0x7F) * 40;
571}
572
AleX Pelosi962aedf2021-01-07 15:39:43 -0800573/* b/177099997 TaskPeriod ----------------------------------------------- */
574
575static inline int reg_to_capacity_uah(u16 val, struct max1720x_chip *chip)
576{
577 const int lsb = max_m5_cap_lsb(chip->model_data);
578
Jenny Hoe63ab0e2021-01-22 16:43:08 +0800579 return reg_to_micro_amp_h(val, chip->RSense, lsb);
AleX Pelosi962aedf2021-01-07 15:39:43 -0800580}
581
Jenny Hoff9f6a62022-06-30 07:23:42 +0000582static inline int reg_to_time_hr(u16 val, struct max1720x_chip *chip)
583{
584 const int lsb = max_m5_cap_lsb(chip->model_data);
585
586 return (val * 32 * lsb) / 10;
587}
588
AleX Pelosi962aedf2021-01-07 15:39:43 -0800589#if 0
590/* TODO: will need in outliers */
591static inline int capacity_uah_to_reg(int capacity, struct max1720x_chip *chip)
592{
593 const int lsb = max_m5_cap_lsb(chip->model_data);
594
595 return micro_amp_h_to_reg(capacity / lsb, chip->RSense);
596}
597#endif
598
599/* log ----------------------------------------------------------------- */
600
Ken Tsou8acade12020-07-09 03:17:35 +0800601static void max1730x_read_log_write_status(struct max1720x_chip *chip,
602 u16 *buffer)
603{
604 u16 i;
605 u16 data = 0;
606 const struct max17x0x_reg *hsty;
607
608 hsty = max17x0x_find_by_tag(&chip->regmap_nvram, MAX17X0X_TAG_HSTY);
609 if (!hsty)
610 return;
611
612 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
613 MAX1730X_COMMAND_HISTORY_RECALL_WRITE_0);
614 msleep(MAX1730X_TRECALL_MS);
615 for (i = hsty->map[1]; i <= hsty->map[3]; i++) {
616 (void)REGMAP_READ(&chip->regmap_nvram, i, &data);
617 *buffer++ = data;
618 }
619}
620
621static void max1730x_read_log_valid_status(struct max1720x_chip *chip,
622 u16 *buffer)
623{
624 u16 i;
625 u16 data = 0;
626 const struct max17x0x_reg *hsty;
627
628 hsty = max17x0x_find_by_tag(&chip->regmap_nvram, MAX17X0X_TAG_HSTY);
629
630 if (!hsty)
631 return;
632
633 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
634 MAX1730X_COMMAND_HISTORY_RECALL_VALID_0);
635 msleep(MAX1730X_TRECALL_MS);
636 (void)REGMAP_READ(&chip->regmap_nvram, hsty->map[4], &data);
637 *buffer++ = data;
638
639 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
640 MAX1730X_COMMAND_HISTORY_RECALL_VALID_1);
641 msleep(MAX1730X_TRECALL_MS);
642 for (i = hsty->map[0]; i <= hsty->map[2]; i++) {
643 (void)REGMAP_READ(&chip->regmap_nvram, i, &data);
644 *buffer++ = data;
645 }
646}
647
648static void max1720x_read_log_write_status(struct max1720x_chip *chip,
649 u16 *buffer)
650{
651 int i;
652 u16 data = 0;
653
654 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
655 MAX1720X_COMMAND_HISTORY_RECALL_WRITE_0);
656 msleep(MAX1720X_TRECALL_MS);
657 for (i = MAX1720X_NVRAM_HISTORY_WRITE_STATUS_START;
658 i <= MAX1720X_NVRAM_HISTORY_END; i++) {
659 (void)REGMAP_READ(&chip->regmap_nvram, i, &data);
660 *buffer++ = data;
661 }
662 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
663 MAX1720X_COMMAND_HISTORY_RECALL_WRITE_1);
664 msleep(MAX1720X_TRECALL_MS);
665 for (i = MAX1720X_HISTORY_START;
666 i <= MAX1720X_NVRAM_HISTORY_WRITE_STATUS_END; i++) {
667 (void)REGMAP_READ(&chip->regmap_nvram, i, &data);
668 *buffer++ = data;
669 }
670}
671
672static void max1720x_read_log_valid_status(struct max1720x_chip *chip,
673 u16 *buffer)
674{
675 int i;
676 u16 data = 0;
677
678 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
679 MAX1720X_COMMAND_HISTORY_RECALL_VALID_0);
680 msleep(MAX1720X_TRECALL_MS);
681 for (i = MAX1720X_NVRAM_HISTORY_VALID_STATUS_START;
682 i <= MAX1720X_NVRAM_HISTORY_END; i++) {
683 (void)REGMAP_READ(&chip->regmap_nvram, i, &data);
684 *buffer++ = data;
685 }
686 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
687 MAX1720X_COMMAND_HISTORY_RECALL_VALID_1);
688 msleep(MAX1720X_TRECALL_MS);
689 for (i = MAX1720X_HISTORY_START;
690 i <= MAX1720X_NVRAM_HISTORY_END; i++) {
691 (void)REGMAP_READ(&chip->regmap_nvram, i, &data);
692 *buffer++ = data;
693 }
694 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
695 MAX1720X_COMMAND_HISTORY_RECALL_VALID_2);
696 msleep(MAX1720X_TRECALL_MS);
697 for (i = MAX1720X_HISTORY_START;
698 i <= MAX1720X_NVRAM_HISTORY_VALID_STATUS_END; i++) {
699 (void)REGMAP_READ(&chip->regmap_nvram, i, &data);
700 *buffer++ = data;
701 }
702}
703
704/* @return the number of pages or negative for error */
705static int get_battery_history_status(struct max1720x_chip *chip,
706 bool *page_status)
707{
708 u16 *write_status, *valid_status;
709 int i, addr_offset, bit_offset, nb_history_pages;
710 int valid_history_entry_count = 0;
711
712 write_status = batt_alloc_array(chip->nb_history_flag_reg, sizeof(u16));
713 if (!write_status)
714 return -ENOMEM;
715
716 valid_status = batt_alloc_array(chip->nb_history_flag_reg, sizeof(u16));
717 if (!valid_status) {
718 kfree(write_status);
719 return -ENOMEM;
720 }
721
722 if (chip->gauge_type == MAX1730X_GAUGE_TYPE) {
723 max1730x_read_log_write_status(chip, write_status);
724 max1730x_read_log_valid_status(chip, valid_status);
725 nb_history_pages = MAX1730X_N_OF_HISTORY_PAGES;
726 } else {
727 max1720x_read_log_write_status(chip, write_status);
728 max1720x_read_log_valid_status(chip, valid_status);
729 nb_history_pages = MAX1720X_N_OF_HISTORY_PAGES;
730 }
731
732 /* Figure out the pages with valid history entry */
733 for (i = 0; i < nb_history_pages; i++) {
734 addr_offset = i / 8;
735 bit_offset = i % 8;
736 page_status[i] =
737 ((write_status[addr_offset] & BIT(bit_offset)) ||
738 (write_status[addr_offset] & BIT(bit_offset + 8))) &&
739 ((valid_status[addr_offset] & BIT(bit_offset)) ||
740 (valid_status[addr_offset] & BIT(bit_offset + 8)));
741 if (page_status[i])
742 valid_history_entry_count++;
743 }
744
745 kfree(write_status);
746 kfree(valid_status);
747
748 return valid_history_entry_count;
749}
750
751static void get_battery_history(struct max1720x_chip *chip,
752 bool *page_status, u16 *history)
753{
754 int i, j, index = 0;
755 u16 data = 0;
756 const struct max17x0x_reg *hsty;
757 u16 command_base = (chip->gauge_type == MAX1730X_GAUGE_TYPE)
758 ? MAX1730X_READ_HISTORY_CMD_BASE
759 : MAX1720X_READ_HISTORY_CMD_BASE;
760
761 hsty = max17x0x_find_by_tag(&chip->regmap_nvram, MAX17X0X_TAG_HSTY);
762 if (!hsty)
763 return;
764
765 for (i = 0; i < chip->nb_history_pages; i++) {
766 if (!page_status[i])
767 continue;
768 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
769 command_base + i);
770 msleep(MAX1720X_TRECALL_MS);
771 for (j = 0; j < chip->history_page_size; j++) {
772 (void)REGMAP_READ(&chip->regmap_nvram,
773 (unsigned int)hsty->map[0] + j,
774 &data);
775 history[index * chip->history_page_size + j] = data;
776 }
777 index++;
778 }
779}
780
781static int format_battery_history_entry(char *temp, int size,
782 int page_size, u16 *line)
783{
784 int length = 0, i;
785
786 for (i = 0; i < page_size; i++) {
787 length += scnprintf(temp + length,
788 size - length, "%04x ",
789 line[i]);
790 }
791
792 if (length > 0)
793 temp[--length] = 0;
794 return length;
795}
796
797/* @return number of valid entries */
798static int max1720x_history_read(struct max1720x_chip *chip,
799 struct max1720x_history *hi)
800{
801 memset(hi, 0, sizeof(*hi));
802
803 hi->page_status = kcalloc(chip->nb_history_pages,
804 sizeof(bool), GFP_KERNEL);
805 if (!hi->page_status)
806 return -ENOMEM;
807
808
809 hi->history_count = get_battery_history_status(chip, hi->page_status);
810 if (hi->history_count < 0) {
811 goto error_exit;
812 } else if (hi->history_count != 0) {
813 const int size = hi->history_count * chip->history_page_size;
814
815 hi->history = batt_alloc_array(size, sizeof(u16));
816 if (!hi->history) {
817 hi->history_count = -ENOMEM;
818 goto error_exit;
819 }
820
821 get_battery_history(chip, hi->page_status, hi->history);
822 }
823
824 return hi->history_count;
825
826error_exit:
827 kfree(hi->page_status);
828 hi->page_status = NULL;
829 return hi->history_count;
830
831}
832
833static void max1720x_history_free(struct max1720x_history *hi)
834{
835 kfree(hi->page_status);
836 kfree(hi->history);
837
838 hi->history = NULL;
839 hi->page_status = NULL;
840 hi->history_count = -1;
841 hi->history_index = 0;
842}
843
844
845/*
846 * Removed the following properties:
847 * POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG
848 * POWER_SUPPLY_PROP_TIME_TO_FULL_AVG
849 * POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
850 * POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
851 * Need to keep the number of properies under UEVENT_NUM_ENVP (minus # of
852 * standard uevent variables).
853 */
854static enum power_supply_property max1720x_battery_props[] = {
855 POWER_SUPPLY_PROP_STATUS,
856 POWER_SUPPLY_PROP_HEALTH,
857 POWER_SUPPLY_PROP_CAPACITY, /* replace with _RAW */
Ken Tsou8acade12020-07-09 03:17:35 +0800858 POWER_SUPPLY_PROP_CHARGE_COUNTER,
859 POWER_SUPPLY_PROP_CHARGE_FULL,
860 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, /* used from gbattery */
861 POWER_SUPPLY_PROP_CURRENT_AVG, /* candidate for tier switch */
862 POWER_SUPPLY_PROP_CURRENT_NOW,
863 POWER_SUPPLY_PROP_CYCLE_COUNT,
864 POWER_SUPPLY_PROP_PRESENT,
Ken Tsou8acade12020-07-09 03:17:35 +0800865 POWER_SUPPLY_PROP_TEMP,
866 POWER_SUPPLY_PROP_VOLTAGE_AVG,
867 POWER_SUPPLY_PROP_VOLTAGE_NOW,
868 POWER_SUPPLY_PROP_VOLTAGE_OCV,
869 POWER_SUPPLY_PROP_TECHNOLOGY,
870 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Ken Tsou8acade12020-07-09 03:17:35 +0800871};
872
873/* ------------------------------------------------------------------------- */
874
875static ssize_t max1720x_get_offmode_charger(struct device *dev,
876 struct device_attribute *attr,
877 char *buf)
878{
879 struct power_supply *psy = container_of(dev, struct power_supply, dev);
880 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
881
882 return scnprintf(buf, PAGE_SIZE, "%hhd\n", chip->offmode_charger);
883}
884
885static ssize_t max1720x_set_offmode_charger(struct device *dev,
886 struct device_attribute *attr,
887 const char *buf, size_t count)
888{
889 struct power_supply *psy = container_of(dev, struct power_supply, dev);
890 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
891
892 if (kstrtobool(buf, &chip->offmode_charger))
893 return -EINVAL;
894
895 return count;
896}
897
898static DEVICE_ATTR(offmode_charger, 0660,
899 max1720x_get_offmode_charger,
900 max1720x_set_offmode_charger);
901
902
903static ssize_t max1720x_model_show_state(struct device *dev,
904 struct device_attribute *attr,
905 char *buf)
906{
907 struct power_supply *psy = container_of(dev, struct power_supply, dev);
908 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
909 ssize_t len = 0;
910
911 if (!chip->model_data)
912 return -EINVAL;
913
914 mutex_lock(&chip->model_lock);
AleX Pelosi7f421272020-12-07 11:24:11 -0800915 len += scnprintf(&buf[len], PAGE_SIZE, "ModelNextUpdate: %d\n",
Ken Tsou8acade12020-07-09 03:17:35 +0800916 chip->model_next_update);
917 len += max_m5_model_state_cstr(&buf[len], PAGE_SIZE - len,
918 chip->model_data);
919 mutex_unlock(&chip->model_lock);
920
921 return len;
922}
923
AleX Pelosi76b63502020-11-03 16:49:44 -0800924/*
AleX Pelosifed7fb12020-11-10 01:22:22 -0800925 * force is true when changing the model via debug props.
926 * NOTE: call holding model_lock
AleX Pelosi76b63502020-11-03 16:49:44 -0800927 */
Jenny Hobad78562021-09-23 13:41:39 +0800928static int max1720x_model_reload(struct max1720x_chip *chip, bool force)
Ken Tsou8acade12020-07-09 03:17:35 +0800929{
Ken Tsou8acade12020-07-09 03:17:35 +0800930 const bool disabled = chip->model_reload == MAX_M5_LOAD_MODEL_DISABLED;
AleX Pelosi962aedf2021-01-07 15:39:43 -0800931 const bool pending = chip->model_reload != MAX_M5_LOAD_MODEL_IDLE;
Jenny Hobad78562021-09-23 13:41:39 +0800932 int version_now, version_load;
933
934 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
935 return -EINVAL;
Ken Tsou8acade12020-07-09 03:17:35 +0800936
937 pr_debug("model_reload=%d force=%d pending=%d disabled=%d\n",
938 chip->model_reload, force, pending, disabled);
939
940 if (!force && (pending || disabled))
Jenny Hobad78562021-09-23 13:41:39 +0800941 return -EEXIST;
942
943 version_now = max_m5_model_read_version(chip->model_data);
944 version_load = max_m5_fg_model_version(chip->model_data);
945
946 if (!force && version_now == version_load)
947 return -EEXIST;
Ken Tsou8acade12020-07-09 03:17:35 +0800948
949 /* REQUEST -> IDLE or set to the number of retries */
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800950 dev_info(chip->dev, "Schedule Load FG Model, ID=%d, ver:%d->%d cap_lsb:%d->%d\n",
AleX Pelosi962aedf2021-01-07 15:39:43 -0800951 chip->batt_id,
Jenny Hobad78562021-09-23 13:41:39 +0800952 version_now,
953 version_load,
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800954 max_m5_model_get_cap_lsb(chip->model_data),
AleX Pelosi962aedf2021-01-07 15:39:43 -0800955 max_m5_cap_lsb(chip->model_data));
956
Ken Tsou8acade12020-07-09 03:17:35 +0800957 chip->model_reload = MAX_M5_LOAD_MODEL_REQUEST;
AleX Pelosi7f421272020-12-07 11:24:11 -0800958 chip->model_ok = false;
Ken Tsou8acade12020-07-09 03:17:35 +0800959 mod_delayed_work(system_wq, &chip->model_work, 0);
Jenny Hobad78562021-09-23 13:41:39 +0800960
961 return 0;
Ken Tsou8acade12020-07-09 03:17:35 +0800962}
963
964static ssize_t max1720x_model_set_state(struct device *dev,
965 struct device_attribute *attr,
966 const char *buf, size_t count)
967{
968 struct power_supply *psy = container_of(dev, struct power_supply, dev);
969 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
970 int ret;
971
972 if (!chip->model_data)
973 return -EINVAL;
974
975 mutex_lock(&chip->model_lock);
976
977 /* read current state from gauge */
978 ret = max_m5_model_read_state(chip->model_data);
979 if (ret < 0) {
980 mutex_unlock(&chip->model_lock);
981 return ret;
982 }
983
984 /* overwrite with userland, will commit at cycle count */
985 ret = max_m5_model_state_sscan(chip->model_data, buf, count);
AleX Pelosi76b63502020-11-03 16:49:44 -0800986 if (ret == 0) {
AleX Pelosifed7fb12020-11-10 01:22:22 -0800987 /* force model state (valid) */
AleX Pelosi76b63502020-11-03 16:49:44 -0800988 chip->model_state_valid = true;
Ken Tsou8acade12020-07-09 03:17:35 +0800989 max1720x_model_reload(chip, true);
AleX Pelosi76b63502020-11-03 16:49:44 -0800990 }
Ken Tsou8acade12020-07-09 03:17:35 +0800991
992 mutex_unlock(&chip->model_lock);
993 return count;
994}
995
AleX Pelosi43986542022-05-03 15:33:18 -0700996
997
998
999/* resistance and impedance ------------------------------------------------ */
1000
1001static int max17x0x_read_resistance_avg(struct max1720x_chip *chip)
1002{
1003 u16 ravg;
1004 int ret = 0;
1005
1006 ret = gbms_storage_read(GBMS_TAG_RAVG, &ravg, sizeof(ravg));
1007 if (ret < 0)
1008 return ret;
1009
1010 return reg_to_resistance_micro_ohms(ravg, chip->RSense);
1011}
1012
1013static int max17x0x_read_resistance_raw(struct max1720x_chip *chip)
1014{
1015 u16 data;
1016 int ret;
1017
1018 ret = REGMAP_READ(&chip->regmap, MAX1720X_RCELL, &data);
1019 if (ret < 0)
1020 return ret;
1021
1022 return data;
1023}
1024
1025static int max17x0x_read_resistance(struct max1720x_chip *chip)
1026{
1027 int rslow;
1028
1029 rslow = max17x0x_read_resistance_raw(chip);
1030 if (rslow < 0)
1031 return rslow;
1032
1033 return reg_to_resistance_micro_ohms(rslow, chip->RSense);
1034}
1035
1036
1037/* ----------------------------------------------------------------------- */
1038
Ken Tsou8acade12020-07-09 03:17:35 +08001039static DEVICE_ATTR(m5_model_state, 0640, max1720x_model_show_state,
1040 max1720x_model_set_state);
1041
Jenny Hoc6bc5882021-02-18 09:21:21 +08001042static ssize_t gmsr_show(struct device *dev,
1043 struct device_attribute *attr,
1044 char *buff)
1045{
1046 struct power_supply *psy = container_of(dev, struct power_supply, dev);
1047 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
1048 ssize_t len = 0;
1049
1050 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
1051 return -EINVAL;
1052
1053 mutex_lock(&chip->model_lock);
1054 len = max_m5_gmsr_state_cstr(&buff[len], PAGE_SIZE);
1055 mutex_unlock(&chip->model_lock);
1056
1057 return len;
1058}
1059
1060static const DEVICE_ATTR_RO(gmsr);
Ken Tsou8acade12020-07-09 03:17:35 +08001061
AleX Pelosi3adb3372020-09-03 00:20:07 -07001062/* Was POWER_SUPPLY_PROP_RESISTANCE_ID */
1063static ssize_t resistance_id_show(struct device *dev,
1064 struct device_attribute *attr,
1065 char *buff)
1066{
1067 struct power_supply *psy = container_of(dev, struct power_supply, dev);
1068 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
1069
1070 return scnprintf(buff, PAGE_SIZE, "%d\n", chip->batt_id);
1071}
1072
1073static const DEVICE_ATTR_RO(resistance_id);
1074
1075/* Was POWER_SUPPLY_PROP_RESISTANCE */
1076static ssize_t resistance_show(struct device *dev,
1077 struct device_attribute *attr,
1078 char *buff)
1079{
1080 struct power_supply *psy = container_of(dev, struct power_supply, dev);
1081 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
AleX Pelosi3adb3372020-09-03 00:20:07 -07001082
AleX Pelosi43986542022-05-03 15:33:18 -07001083 return scnprintf(buff, PAGE_SIZE, "%d\n", max17x0x_read_resistance(chip));
AleX Pelosi3adb3372020-09-03 00:20:07 -07001084}
1085
1086static const DEVICE_ATTR_RO(resistance);
1087
Jenny Ho39b2def2022-03-02 18:18:13 +08001088static ssize_t rc_switch_enable_store(struct device *dev, struct device_attribute *attr,
1089 const char *buff, size_t count)
1090{
1091 struct power_supply *psy = container_of(dev, struct power_supply, dev);
1092 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
1093 bool curr_enable = chip->rc_switch.enable;
1094 int ret;
1095
1096 if (kstrtobool(buff, &chip->rc_switch.enable))
1097 return -EINVAL;
1098
1099 /* Set back to original INI setting when disable */
1100 if (curr_enable == true && chip->rc_switch.enable == false) {
1101 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_LEARNCFG, chip->rc_switch.rc2_learncfg);
1102 dev_info(chip->dev, "Disable RC switch, recover to learncfg %#x. ret=%d",
1103 chip->rc_switch.rc2_learncfg, ret);
1104 }
1105
1106 mod_delayed_work(system_wq, &chip->rc_switch.switch_work, 0);
1107
1108 return count;
1109}
1110
1111static ssize_t rc_switch_enable_show(struct device *dev,
1112 struct device_attribute *attr, char *buff)
1113{
1114 struct power_supply *psy = container_of(dev, struct power_supply, dev);
1115 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
1116
1117 return scnprintf(buff, PAGE_SIZE, "%d\n", chip->rc_switch.enable);
1118}
1119
1120static const DEVICE_ATTR_RW(rc_switch_enable);
AleX Pelosi3adb3372020-09-03 00:20:07 -07001121
Ken Tsou8acade12020-07-09 03:17:35 +08001122/* lsb 1/256, race with max1720x_model_work() */
1123static int max1720x_get_capacity_raw(struct max1720x_chip *chip, u16 *data)
1124{
1125 return REGMAP_READ(&chip->regmap, chip->reg_prop_capacity_raw, data);
1126}
1127
George Lee9833c622021-03-16 16:08:12 -07001128int max1720x_get_capacity(struct i2c_client *client, int *iic_raw)
1129{
AleX Pelosi9a0af672021-04-01 16:04:56 -07001130 struct max1720x_chip *chip;
George Lee9833c622021-03-16 16:08:12 -07001131 u16 temp;
1132 int ret;
1133
AleX Pelosi9a0af672021-04-01 16:04:56 -07001134 if (!client || !iic_raw)
1135 return -EINVAL;
1136
1137 chip = i2c_get_clientdata(client);
George Lee9833c622021-03-16 16:08:12 -07001138 if (!chip)
1139 return -ENODEV;
1140
1141 /* check the rules on reg_prop_capacity_raw */
1142 ret = max1720x_get_capacity_raw(chip, &temp);
1143 if (ret == 0)
1144 *iic_raw = ((int) temp) / 256;
1145
1146 return ret;
1147}
1148EXPORT_SYMBOL_GPL(max1720x_get_capacity);
1149
1150int max1720x_get_voltage_now(struct i2c_client *client, int *volt)
1151{
1152 struct max1720x_chip *chip;
1153 u16 temp;
1154 int ret;
1155
AleX Pelosi9a0af672021-04-01 16:04:56 -07001156 if (!client || !volt)
1157 return -EINVAL;
1158
George Lee9833c622021-03-16 16:08:12 -07001159 chip = i2c_get_clientdata(client);
1160 if (!chip)
1161 return -ENODEV;
1162
1163 ret = max17x0x_reg_read(&chip->regmap, MAX17X0X_TAG_vcel, &temp);
1164 if (ret == 0)
1165 *volt = reg_to_micro_volt(temp);
1166
1167 return ret;
1168}
1169EXPORT_SYMBOL_GPL(max1720x_get_voltage_now);
1170
Ken Tsou8acade12020-07-09 03:17:35 +08001171static int max1720x_get_battery_soc(struct max1720x_chip *chip)
1172{
1173 u16 data;
1174 int capacity, err;
1175
1176 if (chip->fake_capacity >= 0 && chip->fake_capacity <= 100)
1177 return chip->fake_capacity;
1178
1179 err = REGMAP_READ(&chip->regmap, MAX1720X_REPSOC, &data);
1180 if (err)
1181 return err;
1182 capacity = reg_to_percentage(data);
1183
1184 if (capacity == 100 && chip->offmode_charger)
1185 chip->fake_capacity = 100;
1186
1187 return capacity;
1188}
1189
1190static int max1720x_get_battery_vfsoc(struct max1720x_chip *chip)
1191{
1192 u16 data;
1193 int capacity, err;
1194
1195
1196 err = max17x0x_reg_read(&chip->regmap, MAX17X0X_TAG_vfsoc, &data);
1197 if (err)
1198 return err;
1199 capacity = reg_to_percentage(data);
1200
1201 return capacity;
1202}
1203
1204/* TODO: factor with the one in google_bms.c */
1205static char *psy_status_str[] = {
1206 "Unknown", "Charging", "Discharging", "NotCharging", "Full"
1207};
1208
1209static void max1720x_prime_battery_qh_capacity(struct max1720x_chip *chip,
1210 int status)
1211{
1212 u16 mcap = 0, data = 0;
1213
1214 (void)max17x0x_reg_read(&chip->regmap, MAX17X0X_TAG_mcap, &mcap);
1215 chip->current_capacity = mcap;
1216
1217 (void)REGMAP_READ(&chip->regmap, MAX1720X_QH, &data);
1218 chip->previous_qh = reg_to_twos_comp_int(data);
1219
1220 if (chip->regmap_nvram.regmap) {
1221 REGMAP_WRITE(&chip->regmap_nvram, MAX17XXX_QHCA, ~mcap);
1222 dev_info(chip->dev, "Capacity primed to %d on %s\n",
1223 mcap, psy_status_str[status]);
1224
1225 REGMAP_WRITE(&chip->regmap_nvram, MAX17XXX_QHQH, data);
1226 dev_info(chip->dev, "QH primed to %d on %s\n",
1227 data, psy_status_str[status]);
1228 }
1229}
1230
1231/* NOTE: the gauge doesn't know if we are current limited to */
1232static int max1720x_get_battery_status(struct max1720x_chip *chip)
1233{
1234 u16 data = 0;
1235 int current_now, current_avg, ichgterm, vfsoc, soc, fullsocthr;
1236 int status = POWER_SUPPLY_STATUS_UNKNOWN, err;
1237
1238 err = max17x0x_reg_read(&chip->regmap, MAX17X0X_TAG_curr, &data);
1239 if (err)
1240 return -EIO;
1241 current_now = -reg_to_micro_amp(data, chip->RSense);
1242
1243 err = max17x0x_reg_read(&chip->regmap, MAX17X0X_TAG_avgc, &data);
1244 if (err)
1245 return -EIO;
1246 current_avg = -reg_to_micro_amp(data, chip->RSense);
1247
1248 err = REGMAP_READ(&chip->regmap, MAX1720X_ICHGTERM, &data);
1249 if (err)
1250 return -EIO;
1251 ichgterm = reg_to_micro_amp(data, chip->RSense);
1252
1253 err = REGMAP_READ(&chip->regmap, MAX1720X_FULLSOCTHR, &data);
1254 if (err)
1255 return -EIO;
1256 fullsocthr = reg_to_percentage(data);
1257
1258 soc = max1720x_get_battery_soc(chip);
1259 if (soc < 0)
1260 return -EIO;
1261
1262 vfsoc = max1720x_get_battery_vfsoc(chip);
1263 if (vfsoc < 0)
1264 return -EIO;
1265
1266 if (current_avg > -ichgterm && current_avg <= 0) {
1267
1268 if (soc >= fullsocthr) {
1269 const bool needs_prime = (chip->prev_charge_status ==
1270 POWER_SUPPLY_STATUS_CHARGING);
1271
1272 status = POWER_SUPPLY_STATUS_FULL;
1273 if (needs_prime)
1274 max1720x_prime_battery_qh_capacity(chip,
1275 status);
1276 } else {
1277 status = POWER_SUPPLY_STATUS_NOT_CHARGING;
1278 }
1279
1280 } else if (current_now >= -ichgterm) {
1281 status = POWER_SUPPLY_STATUS_DISCHARGING;
1282 } else {
1283 status = POWER_SUPPLY_STATUS_CHARGING;
1284 if (chip->prev_charge_status == POWER_SUPPLY_STATUS_DISCHARGING
1285 && current_avg < -ichgterm)
1286 max1720x_prime_battery_qh_capacity(chip, status);
1287 }
1288
1289 if (status != chip->prev_charge_status)
AleX Pelosibdf1d772021-07-21 00:12:19 -07001290 dev_dbg(chip->dev, "s=%d->%d c=%d avg_c=%d ichgt=%d vfsoc=%d soc=%d fullsocthr=%d\n",
Ken Tsou8acade12020-07-09 03:17:35 +08001291 chip->prev_charge_status,
1292 status, current_now, current_avg,
1293 ichgterm, vfsoc, soc, fullsocthr);
1294
1295 chip->prev_charge_status = status;
1296
1297 return status;
1298}
1299
1300static int max1720x_get_battery_health(struct max1720x_chip *chip)
1301{
1302 /* For health report what ever was recently alerted and clear it */
1303
1304 if (chip->health_status & MAX1720X_STATUS_VMX) {
1305 chip->health_status &= ~MAX1720X_STATUS_VMX;
1306 return POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1307 }
1308
Jenny Ho8d1d51a2022-01-18 15:14:43 +08001309 if ((chip->health_status & MAX1720X_STATUS_TMN) &&
1310 (chip->RConfig & MAX1720X_CONFIG_TS)) {
Ken Tsou8acade12020-07-09 03:17:35 +08001311 chip->health_status &= ~MAX1720X_STATUS_TMN;
1312 return POWER_SUPPLY_HEALTH_COLD;
1313 }
1314
Jenny Ho8d1d51a2022-01-18 15:14:43 +08001315 if ((chip->health_status & MAX1720X_STATUS_TMX) &&
1316 (chip->RConfig & MAX1720X_CONFIG_TS)) {
Ken Tsou8acade12020-07-09 03:17:35 +08001317 chip->health_status &= ~MAX1720X_STATUS_TMX;
Jenny Hod9aece32021-06-24 16:26:52 +08001318 return POWER_SUPPLY_HEALTH_HOT;
Ken Tsou8acade12020-07-09 03:17:35 +08001319 }
1320
1321 return POWER_SUPPLY_HEALTH_GOOD;
1322}
1323
1324static int max1720x_update_battery_qh_based_capacity(struct max1720x_chip *chip)
1325{
1326 u16 data;
1327 int current_qh, err = 0;
1328
1329 err = REGMAP_READ(&chip->regmap, MAX1720X_QH, &data);
1330 if (err)
1331 return err;
1332
1333 current_qh = reg_to_twos_comp_int(data);
1334
1335 /* QH value accumulates as battery charges */
1336 chip->current_capacity -= (chip->previous_qh - current_qh);
1337 chip->previous_qh = current_qh;
1338
1339 return 0;
1340}
1341
1342static void max1720x_restore_battery_qh_capacity(struct max1720x_chip *chip)
1343{
1344 int ret;
1345 int current_qh, nvram_qh;
1346 u16 data = 0, nvram_capacity;
1347
AleX Pelosi43986542022-05-03 15:33:18 -07001348 /* not available without shadow */
Ken Tsou8acade12020-07-09 03:17:35 +08001349 if (!chip->regmap_nvram.regmap) {
1350 max1720x_prime_battery_qh_capacity(chip,
1351 POWER_SUPPLY_STATUS_UNKNOWN);
1352 return;
1353 }
1354
Ken Tsou8acade12020-07-09 03:17:35 +08001355 /* Capacity data is stored as complement so it will not be zero. Using
1356 * zero case to detect new un-primed pack
1357 */
1358 ret = REGMAP_READ(&chip->regmap_nvram, MAX17XXX_QHCA, &data);
1359 if (!ret && data == 0) {
1360 max1720x_prime_battery_qh_capacity(chip,
1361 POWER_SUPPLY_STATUS_UNKNOWN);
1362 return;
1363 }
1364
1365 nvram_capacity = ~data;
1366
1367 ret = REGMAP_READ(&chip->regmap_nvram, MAX17XXX_QHQH, &data);
AleX Pelosi42421012020-09-01 17:09:00 -07001368 if (ret) {
1369 max1720x_prime_battery_qh_capacity(chip,
1370 POWER_SUPPLY_STATUS_UNKNOWN);
1371 return;
1372 }
1373 nvram_qh = reg_to_twos_comp_int(data);
Ken Tsou8acade12020-07-09 03:17:35 +08001374
1375 ret = REGMAP_READ(&chip->regmap, MAX1720X_QH, &data);
AleX Pelosi42421012020-09-01 17:09:00 -07001376 if (ret) {
1377 max1720x_prime_battery_qh_capacity(chip,
1378 POWER_SUPPLY_STATUS_UNKNOWN);
1379 return;
1380 }
Ken Tsou8acade12020-07-09 03:17:35 +08001381 current_qh = reg_to_twos_comp_int(data);
1382
1383 /* QH value accumulates as battery discharges */
1384 chip->current_capacity = (int) nvram_capacity - (nvram_qh - current_qh);
1385 dev_info(chip->dev, "Capacity restored to %d\n",
1386 chip->current_capacity);
1387 chip->previous_qh = current_qh;
1388 dev_info(chip->dev, "QH value restored to %d\n",
1389 chip->previous_qh);
Jenny Ho13c38862021-06-02 17:55:57 +08001390
1391 /* init chip for max1720x done here, change to RepSOC */
1392 chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
Ken Tsou8acade12020-07-09 03:17:35 +08001393}
1394
1395static void max1720x_handle_update_nconvgcfg(struct max1720x_chip *chip,
1396 int temp)
1397{
Robin Peng368f1c92021-09-28 10:54:12 +08001398 int idx = -1;
Ken Tsou8acade12020-07-09 03:17:35 +08001399
1400 if (chip->temp_convgcfg == NULL)
1401 return;
1402
1403 if (temp <= chip->temp_convgcfg[0]) {
1404 idx = 0;
1405 } else if (temp > chip->temp_convgcfg[chip->nb_convgcfg - 1]) {
1406 idx = chip->nb_convgcfg - 1;
1407 } else {
1408 for (idx = 1 ; idx < chip->nb_convgcfg; idx++) {
1409 if (temp > chip->temp_convgcfg[idx - 1] &&
1410 temp <= chip->temp_convgcfg[idx])
1411 break;
1412 }
1413 }
1414 mutex_lock(&chip->convgcfg_lock);
1415 /* We want to switch to higher slot only if above temp + hysteresis
1416 * but when temperature drops, we want to change at the level
1417 */
Ken Tsou8acade12020-07-09 03:17:35 +08001418 if ((idx != chip->curr_convgcfg_idx) &&
1419 (chip->curr_convgcfg_idx == -1 || idx < chip->curr_convgcfg_idx ||
1420 temp >= chip->temp_convgcfg[chip->curr_convgcfg_idx] +
1421 chip->convgcfg_hysteresis)) {
AleX Pelosi02515132021-09-17 19:10:33 -07001422 struct max17x0x_regmap *regmap;
1423
1424 if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
1425 regmap = &chip->regmap;
1426 else
1427 regmap = &chip->regmap_nvram;
1428
1429 REGMAP_WRITE(regmap, MAX1720X_NCONVGCFG, chip->convgcfg_values[idx]);
Ken Tsou8acade12020-07-09 03:17:35 +08001430 chip->curr_convgcfg_idx = idx;
1431 dev_info(chip->dev, "updating nConvgcfg to 0x%04x as temp is %d (idx:%d)\n",
1432 chip->convgcfg_values[idx], temp, idx);
1433 }
1434 mutex_unlock(&chip->convgcfg_lock);
1435}
1436
Jenny Ho80a583b2021-11-15 01:46:25 +08001437static void max1720x_handle_update_filtercfg(struct max1720x_chip *chip,
1438 int temp)
1439{
1440 struct max1720x_dyn_filtercfg *filtercfg = &chip->dyn_filtercfg;
1441 s16 hysteresis_temp;
1442 u16 filtercfg_val;
1443
1444 if (filtercfg->temp == -1)
1445 return;
1446
Jenny Ho507498b2022-05-11 14:31:53 +08001447 if (chip->por)
1448 return;
1449
Jenny Ho80a583b2021-11-15 01:46:25 +08001450 mutex_lock(&filtercfg->lock);
1451 if (temp <= filtercfg->temp)
1452 filtercfg_val = filtercfg->adjust_val;
1453 else
1454 filtercfg_val = filtercfg->default_val;
1455
1456 hysteresis_temp = filtercfg->temp + filtercfg->hysteresis;
1457 if ((filtercfg_val != filtercfg->curr_val) &&
1458 (filtercfg->curr_val == 0 || temp < filtercfg->temp ||
1459 temp >= hysteresis_temp)) {
1460 struct max17x0x_regmap *regmap;
1461
1462 if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
1463 regmap = &chip->regmap;
1464 else
1465 regmap = &chip->regmap_nvram;
1466
1467 REGMAP_WRITE(regmap, MAX1720X_FILTERCFG, filtercfg_val);
1468 dev_info(chip->dev, "updating filtercfg to 0x%04x as temp is %d\n",
1469 filtercfg_val, temp);
1470 filtercfg->curr_val = filtercfg_val;
1471 }
1472 mutex_unlock(&filtercfg->lock);
1473}
1474
Jenny Ho263f1452020-10-30 02:56:17 +08001475#define EEPROM_CC_OVERFLOW_BIT BIT(15)
Jenny Ho70c3d772021-03-12 17:49:43 +08001476#define MAXIM_CYCLE_COUNT_RESET 655
Jenny Ho263f1452020-10-30 02:56:17 +08001477static void max1720x_restore_battery_cycle(struct max1720x_chip *chip)
1478{
1479 int ret = 0;
1480 u16 eeprom_cycle, reg_cycle;
1481
1482 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
1483 return;
1484
1485 ret = REGMAP_READ(&chip->regmap, MAX1720X_CYCLES, &reg_cycle);
1486 if (ret < 0) {
Jenny Ho70c3d772021-03-12 17:49:43 +08001487 dev_info(chip->dev, "Fail to read reg %#x (%d)",
Jenny Ho263f1452020-10-30 02:56:17 +08001488 MAX1720X_CYCLES, ret);
1489 return;
1490 }
1491
Jenny Ho70c3d772021-03-12 17:49:43 +08001492 ret = gbms_storage_read(GBMS_TAG_CNHS, &chip->eeprom_cycle,
1493 sizeof(chip->eeprom_cycle));
Jenny Ho263f1452020-10-30 02:56:17 +08001494 if (ret < 0) {
Jenny Ho70c3d772021-03-12 17:49:43 +08001495 dev_info(chip->dev, "Fail to read eeprom cycle count (%d)", ret);
Jenny Ho263f1452020-10-30 02:56:17 +08001496 return;
1497 }
1498
Jenny Ho70c3d772021-03-12 17:49:43 +08001499 if (chip->eeprom_cycle == 0xFFFF) { /* empty storage */
Jenny Ho263f1452020-10-30 02:56:17 +08001500 reg_cycle /= 2; /* save half value to record over 655 cycles case */
1501 ret = gbms_storage_write(GBMS_TAG_CNHS, &reg_cycle, sizeof(reg_cycle));
1502 if (ret < 0)
Jenny Ho70c3d772021-03-12 17:49:43 +08001503 dev_info(chip->dev, "Fail to write eeprom cycle (%d)", ret);
1504 else
1505 chip->eeprom_cycle = reg_cycle;
1506 return;
Jenny Ho263f1452020-10-30 02:56:17 +08001507 }
Jenny Ho70c3d772021-03-12 17:49:43 +08001508
Jenny Hof7572102021-11-15 16:26:12 +08001509 if (chip->eeprom_cycle & EEPROM_CC_OVERFLOW_BIT)
1510 chip->cycle_count_offset = MAXIM_CYCLE_COUNT_RESET;
Jenny Ho70c3d772021-03-12 17:49:43 +08001511
1512 eeprom_cycle = (chip->eeprom_cycle & 0x7FFF) << 1;
1513 dev_info(chip->dev, "reg_cycle:%d, eeprom_cycle:%d, update:%c",
1514 reg_cycle, eeprom_cycle, eeprom_cycle > reg_cycle ? 'Y' : 'N');
Jenny Hobad78562021-09-23 13:41:39 +08001515 if (eeprom_cycle > reg_cycle) {
1516 ret = REGMAP_WRITE_VERIFY(&chip->regmap, MAX1720X_CYCLES, eeprom_cycle);
1517 if (ret < 0)
1518 dev_warn(chip->dev, "fail to update cycles (%d)", ret);
1519 }
Jenny Ho263f1452020-10-30 02:56:17 +08001520}
1521
Jenny Ho70c3d772021-03-12 17:49:43 +08001522static u16 max1720x_save_battery_cycle(const struct max1720x_chip *chip,
1523 u16 reg_cycle)
Jenny Ho263f1452020-10-30 02:56:17 +08001524{
Jenny Ho70c3d772021-03-12 17:49:43 +08001525 int ret = 0;
1526 u16 eeprom_cycle = chip->eeprom_cycle;
Jenny Ho263f1452020-10-30 02:56:17 +08001527
Jenny Ho70c3d772021-03-12 17:49:43 +08001528 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
1529 return eeprom_cycle;
Jenny Ho263f1452020-10-30 02:56:17 +08001530
Jenny Ho0b23ad92022-01-06 11:05:03 +08001531 if (chip->por || reg_cycle == 0)
Jenny Hobad78562021-09-23 13:41:39 +08001532 return eeprom_cycle;
1533
Jenny Ho70c3d772021-03-12 17:49:43 +08001534 /* save half value to record over 655 cycles case */
1535 reg_cycle /= 2;
1536
1537 /* Over 655 cycles */
Jenny Ho263f1452020-10-30 02:56:17 +08001538 if (reg_cycle < eeprom_cycle)
1539 reg_cycle |= EEPROM_CC_OVERFLOW_BIT;
Jenny Ho70c3d772021-03-12 17:49:43 +08001540
1541 if (reg_cycle <= eeprom_cycle)
1542 return eeprom_cycle;
1543
1544 ret = gbms_storage_write(GBMS_TAG_CNHS, &reg_cycle,
1545 sizeof(reg_cycle));
Jenny Ho6a391fd2022-08-10 23:33:14 +00001546 if (ret < 0) {
Jenny Hoa1e85e92022-05-16 13:36:05 +08001547 dev_info(chip->dev, "Fail to write %d eeprom cycle count (%d)", reg_cycle, ret);
Jenny Ho6a391fd2022-08-10 23:33:14 +00001548 } else {
1549 dev_info(chip->dev, "update saved cycle:%d -> %d\n", eeprom_cycle, reg_cycle);
Jenny Ho70c3d772021-03-12 17:49:43 +08001550 eeprom_cycle = reg_cycle;
Jenny Ho6a391fd2022-08-10 23:33:14 +00001551 }
Jenny Ho70c3d772021-03-12 17:49:43 +08001552
1553 return eeprom_cycle;
Jenny Ho263f1452020-10-30 02:56:17 +08001554}
1555
Ken Tsou8acade12020-07-09 03:17:35 +08001556#define MAX17201_HIST_CYCLE_COUNT_OFFSET 0x4
1557#define MAX17201_HIST_TIME_OFFSET 0xf
1558
1559/* WA for cycle count reset.
1560 * max17201 fuel gauge rolls over the cycle count to 0 and burns
1561 * an history entry with 0 cycles when the cycle count exceeds
1562 * 655. This code workaround the issue adding 655 to the cycle
1563 * count if the fuel gauge history has an entry with 0 cycles and
1564 * non 0 time-in-field.
1565 */
Jenny Hof5be5122021-01-08 18:43:45 +08001566static int max1720x_get_cycle_count_offset(struct max1720x_chip *chip)
Ken Tsou8acade12020-07-09 03:17:35 +08001567{
Jenny Ho263f1452020-10-30 02:56:17 +08001568 int offset = 0;
1569 /*
1570 * uses history on devices that have it (max1720x), use EEPROM
1571 * in others. it might be written in terms of storage.
1572 */
1573 if (chip->gauge_type == MAX_M5_GAUGE_TYPE) {
Jenny Ho70c3d772021-03-12 17:49:43 +08001574 if (chip->eeprom_cycle & EEPROM_CC_OVERFLOW_BIT)
Jenny Ho263f1452020-10-30 02:56:17 +08001575 offset = MAXIM_CYCLE_COUNT_RESET;
1576 } else {
1577 int i, history_count;
1578 struct max1720x_history hi;
Jenny Hof5be5122021-01-08 18:43:45 +08001579
Jenny Ho263f1452020-10-30 02:56:17 +08001580 if (!chip->history_page_size)
1581 return 0;
Jenny Hof5be5122021-01-08 18:43:45 +08001582
Jenny Ho263f1452020-10-30 02:56:17 +08001583 mutex_lock(&chip->history_lock);
1584 history_count = max1720x_history_read(chip, &hi);
1585 if (history_count < 0) {
1586 mutex_unlock(&chip->history_lock);
1587 return 0;
Jenny Hof5be5122021-01-08 18:43:45 +08001588 }
Jenny Ho263f1452020-10-30 02:56:17 +08001589 for (i = 0; i < history_count; i++) {
1590 u16 *entry = &hi.history[i * chip->history_page_size];
1591
1592 if (entry[MAX17201_HIST_CYCLE_COUNT_OFFSET] == 0 &&
1593 entry[MAX17201_HIST_TIME_OFFSET] != 0) {
1594 offset += MAXIM_CYCLE_COUNT_RESET;
1595 break;
1596 }
1597 }
1598 mutex_unlock(&chip->history_lock);
1599
1600 dev_dbg(chip->dev, "history_count=%d page_size=%d i=%d offset=%d\n",
1601 history_count, chip->history_page_size, i, offset);
1602
1603 max1720x_history_free(&hi);
Jenny Hof5be5122021-01-08 18:43:45 +08001604 }
Jenny Hof5be5122021-01-08 18:43:45 +08001605
Ken Tsou8acade12020-07-09 03:17:35 +08001606 return offset;
1607}
1608
1609static int max1720x_get_cycle_count(struct max1720x_chip *chip)
1610{
1611 int err, cycle_count;
Jenny Ho70c3d772021-03-12 17:49:43 +08001612 u16 reg_cycle;
Ken Tsou8acade12020-07-09 03:17:35 +08001613
AleX Pelosid7c3e632021-09-17 16:33:48 -07001614 /*
1615 * Corner case: battery under 3V hit POR without irq.
Jenny Hod4721532021-08-12 12:29:25 +08001616 * cycles reset in this situation, incorrect data
1617 */
1618 if (chip->por)
1619 return -ECANCELED;
1620
Jenny Ho70c3d772021-03-12 17:49:43 +08001621 err = REGMAP_READ(&chip->regmap, MAX1720X_CYCLES, &reg_cycle);
Ken Tsou8acade12020-07-09 03:17:35 +08001622 if (err < 0)
1623 return err;
1624
George Lee014b6742021-05-17 11:25:22 -07001625 cycle_count = reg_to_cycles((u32)reg_cycle, chip->gauge_type);
Jenny Hof5be5122021-01-08 18:43:45 +08001626 if ((chip->cycle_count == -1) ||
1627 ((cycle_count + chip->cycle_count_offset) < chip->cycle_count))
1628 chip->cycle_count_offset =
1629 max1720x_get_cycle_count_offset(chip);
Ken Tsou8acade12020-07-09 03:17:35 +08001630
Jenny Ho70c3d772021-03-12 17:49:43 +08001631 chip->eeprom_cycle = max1720x_save_battery_cycle(chip, reg_cycle);
Jenny Ho263f1452020-10-30 02:56:17 +08001632
Jenny Hof5be5122021-01-08 18:43:45 +08001633 chip->cycle_count = cycle_count + chip->cycle_count_offset;
1634
Jenny Ho062fe712022-10-03 15:06:39 +08001635 if (chip->model_ok && reg_cycle >= chip->model_next_update) {
1636 err = max1720x_set_next_update(chip);
1637 if (err < 0)
1638 dev_err(chip->dev, "%s cannot set next update (%d)\n",
1639 __func__, err);
1640 }
1641
Jenny Hof5be5122021-01-08 18:43:45 +08001642 return chip->cycle_count;
Ken Tsou8acade12020-07-09 03:17:35 +08001643}
1644
1645static void max1720x_handle_update_empty_voltage(struct max1720x_chip *chip,
1646 int temp)
1647{
1648 int cycle, cycle_idx, temp_idx, chg_st, ret = 0;
1649 u16 empty_volt_cfg, reg, vempty = 0;
1650
1651 if (chip->empty_voltage == NULL)
1652 return;
1653
1654 chg_st = max1720x_get_battery_status(chip);
1655 if (chg_st < 0)
1656 return;
1657
1658 cycle = max1720x_get_cycle_count(chip);
1659 if (cycle < 0)
1660 return;
1661
1662 ret = REGMAP_READ(&chip->regmap, MAX1720X_VEMPTY, &vempty);
1663 if (ret < 0)
1664 return;
1665
1666 cycle_idx = cycle / CYCLE_BUCKET_SIZE;
1667 if (cycle_idx > (NB_CYCLE_BUCKETS - 1))
1668 cycle_idx = NB_CYCLE_BUCKETS - 1;
1669
1670 if (temp < 0) {
1671 temp_idx = 0;
1672 } else {
1673 const int idx = temp / TEMP_BUCKET_SIZE + 1;
1674 const int temp_buckets = chip->nb_empty_voltage /
1675 NB_CYCLE_BUCKETS;
1676
1677 temp_idx = idx < (temp_buckets - 1) ? idx : (temp_buckets - 1);
1678 }
1679
1680 empty_volt_cfg = MAX1720_EMPTY_VOLTAGE(chip, temp_idx, cycle_idx);
1681 reg = (empty_volt_cfg / 10) << 7 | (vempty & 0x7F);
1682 if ((reg > vempty) ||
1683 (reg < vempty && chg_st != POWER_SUPPLY_STATUS_DISCHARGING)) {
1684 REGMAP_WRITE(&chip->regmap, MAX1720X_VEMPTY, reg);
1685
1686 pr_debug("updating empty_voltage to %d(0x%04X), temp:%d(%d), cycle:%d(%d)\n",
1687 empty_volt_cfg, reg,
1688 temp, temp_idx,
1689 cycle, cycle_idx);
1690 }
1691}
1692
1693/* Capacity Estimation functions*/
1694static int batt_ce_regmap_read(struct max17x0x_regmap *map,
1695 const struct max17x0x_reg *bcea,
1696 u32 reg, u16 *data)
1697{
1698 int err;
1699 u16 val;
1700
1701 if (!bcea)
1702 return -EINVAL;
1703
1704 err = REGMAP_READ(map, bcea->map[reg], &val);
1705 if (err)
1706 return err;
1707
1708 switch(reg) {
1709 case CE_DELTA_CC_SUM_REG:
1710 case CE_DELTA_VFSOC_SUM_REG:
1711 *data = val;
1712 break;
1713 case CE_CAP_FILTER_COUNT:
1714 val = val & 0x0F00;
1715 *data = val >> 8;
1716 break;
1717 default:
1718 break;
1719 }
1720
1721 return err;
1722}
1723
1724static int batt_ce_regmap_write(struct max17x0x_regmap *map,
1725 const struct max17x0x_reg *bcea,
1726 u32 reg, u16 data)
1727{
1728 int err = -EINVAL;
1729 u16 val;
1730
1731 if (!bcea)
1732 return -EINVAL;
1733
1734 switch(reg) {
1735 case CE_DELTA_CC_SUM_REG:
1736 case CE_DELTA_VFSOC_SUM_REG:
1737 err = REGMAP_WRITE(map, bcea->map[reg], data);
1738 break;
1739 case CE_CAP_FILTER_COUNT:
1740 err = REGMAP_READ(map, bcea->map[reg], &val);
1741 if (err)
1742 return err;
1743 val = val & 0xF0FF;
1744 if (data > CE_FILTER_COUNT_MAX)
1745 val = val | 0x0F00;
1746 else
1747 val = val | (data << 8);
1748 err = REGMAP_WRITE(map, bcea->map[reg], val);
1749 break;
1750 default:
1751 break;
1752 }
1753
1754 return err;
1755}
1756
1757static void batt_ce_dump_data(const struct gbatt_capacity_estimation *cap_esti,
1758 struct logbuffer *log)
1759{
1760 logbuffer_log(log, "cap_filter_count: %d"
1761 " start_cc: %d"
1762 " start_vfsoc: %d"
1763 " delta_cc_sum: %d"
1764 " delta_vfsoc_sum: %d"
1765 " state: %d"
Jenny Ho5381a6f2021-08-11 14:34:45 +08001766 " cable: %d",
Ken Tsou8acade12020-07-09 03:17:35 +08001767 cap_esti->cap_filter_count,
1768 cap_esti->start_cc,
1769 cap_esti->start_vfsoc,
1770 cap_esti->delta_cc_sum,
1771 cap_esti->delta_vfsoc_sum,
1772 cap_esti->estimate_state,
1773 cap_esti->cable_in);
1774}
1775
1776static int batt_ce_load_data(struct max17x0x_regmap *map,
1777 struct gbatt_capacity_estimation *cap_esti)
1778{
1779 u16 data;
1780 const struct max17x0x_reg *bcea = cap_esti->bcea;
1781
1782 cap_esti->estimate_state = ESTIMATE_NONE;
1783 if (batt_ce_regmap_read(map, bcea, CE_DELTA_CC_SUM_REG, &data) == 0)
1784 cap_esti->delta_cc_sum = data;
1785 else
1786 cap_esti->delta_cc_sum = 0;
1787
1788 if (batt_ce_regmap_read(map, bcea, CE_DELTA_VFSOC_SUM_REG, &data) == 0)
1789 cap_esti->delta_vfsoc_sum = data;
1790 else
1791 cap_esti->delta_vfsoc_sum = 0;
1792
1793 if (batt_ce_regmap_read(map, bcea, CE_CAP_FILTER_COUNT, &data) == 0)
1794 cap_esti->cap_filter_count = data;
1795 else
1796 cap_esti->cap_filter_count = 0;
1797 return 0;
1798}
1799
1800/* call holding &cap_esti->batt_ce_lock */
1801static void batt_ce_store_data(struct max17x0x_regmap *map,
1802 struct gbatt_capacity_estimation *cap_esti)
1803{
1804 if (cap_esti->cap_filter_count <= CE_FILTER_COUNT_MAX) {
1805 batt_ce_regmap_write(map, cap_esti->bcea,
1806 CE_CAP_FILTER_COUNT,
1807 cap_esti->cap_filter_count);
1808 }
1809
1810 batt_ce_regmap_write(map, cap_esti->bcea,
1811 CE_DELTA_VFSOC_SUM_REG,
1812 cap_esti->delta_vfsoc_sum);
1813 batt_ce_regmap_write(map, cap_esti->bcea,
1814 CE_DELTA_CC_SUM_REG,
1815 cap_esti->delta_cc_sum);
1816}
1817
1818/* call holding &cap_esti->batt_ce_lock */
1819static void batt_ce_stop_estimation(struct gbatt_capacity_estimation *cap_esti,
1820 int reason)
1821{
1822 cap_esti->estimate_state = reason;
1823 cap_esti->start_vfsoc = 0;
1824 cap_esti->start_cc = 0;
1825}
1826
1827static int batt_ce_full_estimate(struct gbatt_capacity_estimation *ce)
1828{
1829 return (ce->cap_filter_count > 0) && (ce->delta_vfsoc_sum > 0) ?
1830 ce->delta_cc_sum / ce->delta_vfsoc_sum : -1;
1831}
1832
1833/* Measure the deltaCC, deltaVFSOC and CapacityFiltered */
1834static void batt_ce_capacityfiltered_work(struct work_struct *work)
1835{
1836 struct max1720x_chip *chip = container_of(work, struct max1720x_chip,
1837 cap_estimate.settle_timer.work);
1838 struct gbatt_capacity_estimation *cap_esti = &chip->cap_estimate;
Jenny Hoe63ab0e2021-01-22 16:43:08 +08001839 const int lsb = max_m5_cap_lsb(chip->model_data);
Ken Tsou8acade12020-07-09 03:17:35 +08001840 int settle_cc = 0, settle_vfsoc = 0;
1841 int delta_cc = 0, delta_vfsoc = 0;
1842 int cc_sum = 0, vfsoc_sum = 0;
1843 bool valid_estimate = false;
1844 int rc = 0;
David Lin32a61172021-02-21 23:35:25 -08001845 int data;
Ken Tsou8acade12020-07-09 03:17:35 +08001846
1847 mutex_lock(&cap_esti->batt_ce_lock);
1848
1849 /* race with disconnect */
1850 if (!cap_esti->cable_in ||
1851 cap_esti->estimate_state != ESTIMATE_PENDING) {
1852 goto exit;
1853 }
1854
1855 rc = max1720x_update_battery_qh_based_capacity(chip);
1856 if (rc < 0)
1857 goto ioerr;
1858
Jenny Hoe63ab0e2021-01-22 16:43:08 +08001859 settle_cc = reg_to_micro_amp_h(chip->current_capacity, chip->RSense, lsb);
Ken Tsou8acade12020-07-09 03:17:35 +08001860
1861 data = max1720x_get_battery_vfsoc(chip);
1862 if (data < 0)
1863 goto ioerr;
1864
1865 settle_vfsoc = data;
1866 settle_cc = settle_cc / 1000;
1867 delta_cc = settle_cc - cap_esti->start_cc;
1868 delta_vfsoc = settle_vfsoc - cap_esti->start_vfsoc;
1869
1870 if ((delta_cc > 0) && (delta_vfsoc > 0)) {
1871
1872 cc_sum = delta_cc + cap_esti->delta_cc_sum;
1873 vfsoc_sum = delta_vfsoc + cap_esti->delta_vfsoc_sum;
1874
1875 if (cap_esti->cap_filter_count >= cap_esti->cap_filt_length) {
1876 const int filter_divisor = cap_esti->cap_filt_length;
1877
1878 cc_sum -= cap_esti->delta_cc_sum/filter_divisor;
1879 vfsoc_sum -= cap_esti->delta_vfsoc_sum/filter_divisor;
1880 }
1881
1882 cap_esti->cap_filter_count++;
1883 cap_esti->delta_cc_sum = cc_sum;
1884 cap_esti->delta_vfsoc_sum = vfsoc_sum;
1885 batt_ce_store_data(&chip->regmap_nvram, &chip->cap_estimate);
1886
1887 valid_estimate = true;
1888 }
1889
1890ioerr:
1891 batt_ce_stop_estimation(cap_esti, ESTIMATE_DONE);
1892
1893exit:
1894 logbuffer_log(chip->ce_log,
Jenny Ho5381a6f2021-08-11 14:34:45 +08001895 "valid=%d settle[cc=%d, vfsoc=%d], delta[cc=%d,vfsoc=%d] ce[%d]=%d",
Ken Tsou8acade12020-07-09 03:17:35 +08001896 valid_estimate,
1897 settle_cc, settle_vfsoc, delta_cc, delta_vfsoc,
1898 cap_esti->cap_filter_count,
1899 batt_ce_full_estimate(cap_esti));
1900
1901 mutex_unlock(&cap_esti->batt_ce_lock);
1902
1903 /* force to update uevent to framework side. */
1904 if (valid_estimate)
1905 power_supply_changed(chip->psy);
1906}
1907
1908/*
1909 * batt_ce_init(): estimate_state = ESTIMATE_NONE
1910 * batt_ce_start(): estimate_state = ESTIMATE_NONE -> ESTIMATE_PENDING
1911 * batt_ce_capacityfiltered_work(): ESTIMATE_PENDING->ESTIMATE_DONE
1912 */
1913static int batt_ce_start(struct gbatt_capacity_estimation *cap_esti,
1914 int cap_tsettle_ms)
1915{
1916 mutex_lock(&cap_esti->batt_ce_lock);
1917
1918 /* Still has cable and estimate is not pending or cancelled */
1919 if (!cap_esti->cable_in || cap_esti->estimate_state != ESTIMATE_NONE)
1920 goto done;
1921
1922 pr_info("EOC: Start the settle timer\n");
1923 cap_esti->estimate_state = ESTIMATE_PENDING;
1924 schedule_delayed_work(&cap_esti->settle_timer,
1925 msecs_to_jiffies(cap_tsettle_ms));
1926
1927done:
1928 mutex_unlock(&cap_esti->batt_ce_lock);
1929 return 0;
1930}
1931
1932static int batt_ce_init(struct gbatt_capacity_estimation *cap_esti,
1933 struct max1720x_chip *chip)
1934{
David Lin32a61172021-02-21 23:35:25 -08001935 int rc, vfsoc;
Jenny Hoe63ab0e2021-01-22 16:43:08 +08001936 const int lsb = max_m5_cap_lsb(chip->model_data);
Ken Tsou8acade12020-07-09 03:17:35 +08001937
1938 rc = max1720x_update_battery_qh_based_capacity(chip);
1939 if (rc < 0)
1940 return -EIO;
1941
1942 vfsoc = max1720x_get_battery_vfsoc(chip);
1943 if (vfsoc < 0)
1944 return -EIO;
1945
1946 cap_esti->start_vfsoc = vfsoc;
1947 cap_esti->start_cc = reg_to_micro_amp_h(chip->current_capacity,
Jenny Hoe63ab0e2021-01-22 16:43:08 +08001948 chip->RSense, lsb) / 1000;
Ken Tsou8acade12020-07-09 03:17:35 +08001949 /* Capacity Estimation starts only when the state is NONE */
1950 cap_esti->estimate_state = ESTIMATE_NONE;
1951 return 0;
1952}
1953
1954/* ------------------------------------------------------------------------- */
AleX Pelosi43986542022-05-03 15:33:18 -07001955
Ken Tsou8acade12020-07-09 03:17:35 +08001956#define SEL_RES_AVG 0
1957#define SEL_RES_FILTER_COUNT 1
1958static int batt_res_registers(struct max1720x_chip *chip, bool bread,
AleX Pelosi3adb3372020-09-03 00:20:07 -07001959 int isel, u16 *data)
Ken Tsou8acade12020-07-09 03:17:35 +08001960{
1961 int err = -EINVAL;
1962 const struct max17x0x_reg *bres;
1963 u16 res_filtered, res_filt_count, val;
1964
1965 bres = max17x0x_find_by_tag(&chip->regmap_nvram, MAX17X0X_TAG_BRES);
1966 if (!bres)
1967 return err;
1968
1969 switch (isel) {
1970 case SEL_RES_AVG:
1971 if (bread) {
1972 err = REGMAP_READ(&chip->regmap_nvram, bres->map[0],
1973 &res_filtered);
1974 if (err)
1975 return err;
1976
1977 *data = res_filtered;
1978 return 0;
1979 }
1980 err = REGMAP_WRITE(&chip->regmap_nvram, bres->map[0], *data);
1981 break;
1982 case SEL_RES_FILTER_COUNT:
1983 err = REGMAP_READ(&chip->regmap_nvram, bres->map[1], &val);
1984 if (err)
1985 return err;
1986
1987 if (bread) {
1988 res_filt_count = (val & 0xF000) >> 12;
1989 *data = res_filt_count;
1990 return 0;
1991 }
AleX Pelosi3adb3372020-09-03 00:20:07 -07001992
Ken Tsou8acade12020-07-09 03:17:35 +08001993 res_filt_count = (val & 0x0FFF) | (*data << 12);
1994 err = REGMAP_WRITE(&chip->regmap_nvram, bres->map[1],
1995 res_filt_count);
1996 break;
1997 default:
1998 break;
1999 }
2000
2001 return err;
2002}
2003
AleX Pelosi43986542022-05-03 15:33:18 -07002004static int max1720x_health_write_ai(u16 act_impedance, u16 act_timerh)
Jack Wuecfe7562022-03-17 18:17:53 +08002005{
AleX Pelosi43bec422022-04-27 21:59:19 -07002006 int ret;
2007
AleX Pelosi43986542022-05-03 15:33:18 -07002008 ret = gbms_storage_write(GBMS_TAG_ACIM, &act_impedance, sizeof(act_impedance));
AleX Pelosi43bec422022-04-27 21:59:19 -07002009 if (ret < 0)
AleX Pelosi43986542022-05-03 15:33:18 -07002010 return -EIO;
AleX Pelosi43bec422022-04-27 21:59:19 -07002011
AleX Pelosi43986542022-05-03 15:33:18 -07002012 ret = gbms_storage_write(GBMS_TAG_THAS, &act_timerh, sizeof(act_timerh));
2013 if (ret < 0)
2014 return -EIO;
2015
2016 return ret;
AleX Pelosi43bec422022-04-27 21:59:19 -07002017}
2018
Jack Wuecfe7562022-03-17 18:17:53 +08002019/* call holding chip->model_lock */
2020static int max1720x_check_impedance(struct max1720x_chip *chip, u16 *th)
2021{
2022 struct max17x0x_regmap *map = &chip->regmap;
2023 int soc, temp, cycle_count, ret;
2024 u16 data, timerh;
2025
2026 if (!chip->model_state_valid)
2027 return -EAGAIN;
2028
2029 soc = max1720x_get_battery_soc(chip);
2030 if (soc < BHI_IMPEDANCE_SOC_LO || soc > BHI_IMPEDANCE_SOC_HI)
AleX Pelosic1cd4752022-05-04 02:15:02 -07002031 return -EAGAIN;
Jack Wuecfe7562022-03-17 18:17:53 +08002032
2033 ret = max17x0x_reg_read(map, MAX17X0X_TAG_temp, &data);
2034 if (ret < 0)
AleX Pelosic1cd4752022-05-04 02:15:02 -07002035 return -EIO;
Jack Wuecfe7562022-03-17 18:17:53 +08002036
2037 temp = reg_to_deci_deg_cel(data);
2038 if (temp < BHI_IMPEDANCE_TEMP_LO || temp > BHI_IMPEDANCE_TEMP_HI)
AleX Pelosic1cd4752022-05-04 02:15:02 -07002039 return -EAGAIN;
Jack Wuecfe7562022-03-17 18:17:53 +08002040
2041 cycle_count = max1720x_get_cycle_count(chip);
2042 if (cycle_count < 0)
2043 return -EINVAL;
2044
AleX Pelosic1cd4752022-05-04 02:15:02 -07002045 ret = REGMAP_READ(&chip->regmap, MAX1720X_TIMERH, &timerh);
2046 if (ret < 0 || timerh == 0)
2047 return -EINVAL;
2048
Jack Wuecfe7562022-03-17 18:17:53 +08002049 /* wait for a few cyles and time in field before validating the value */
2050 if (cycle_count < BHI_IMPEDANCE_CYCLE_CNT || timerh < BHI_IMPEDANCE_TIMERH)
2051 return -ENODATA;
Jack Wu94fd2c72022-03-29 20:44:19 +08002052
Jack Wuecfe7562022-03-17 18:17:53 +08002053 *th = timerh;
2054 return 0;
2055}
2056
AleX Pelosi43bec422022-04-27 21:59:19 -07002057/* will return error if the value is not valid */
AleX Pelosi43986542022-05-03 15:33:18 -07002058static int max1720x_health_get_ai(struct max1720x_chip *chip)
AleX Pelosi43bec422022-04-27 21:59:19 -07002059{
2060 u16 act_impedance, act_timerh;
2061 int ret;
2062
2063 if (chip->bhi_acim != 0)
2064 return chip->bhi_acim;
2065
2066 /* read both and recalculate for compatibility */
2067 ret = gbms_storage_read(GBMS_TAG_ACIM, &act_impedance, sizeof(act_impedance));
2068 if (ret < 0)
2069 return -EIO;
2070
2071 ret = gbms_storage_read(GBMS_TAG_THAS, &act_timerh, sizeof(act_timerh));
2072 if (ret < 0)
2073 return -EIO;
2074
AleX Pelosi43986542022-05-03 15:33:18 -07002075 /* need to get starting impedance (if qualified) */
AleX Pelosic1cd4752022-05-04 02:15:02 -07002076 if (act_impedance == 0xffff || act_timerh == 0xffff)
2077 return -EINVAL;
AleX Pelosi43bec422022-04-27 21:59:19 -07002078
AleX Pelosi43986542022-05-03 15:33:18 -07002079 /* not zero, not negative */
2080 chip->bhi_acim = reg_to_resistance_micro_ohms(act_impedance, chip->RSense);;
AleX Pelosi43bec422022-04-27 21:59:19 -07002081
AleX Pelosi43986542022-05-03 15:33:18 -07002082 /* TODO: corrrect impedance with timerh */
AleX Pelosi43bec422022-04-27 21:59:19 -07002083
Jenny Hoa1e85e92022-05-16 13:36:05 +08002084 dev_info(chip->dev, "%s: chip->bhi_acim =%d act_impedance=%x act_timerh=%x\n",
2085 __func__, chip->bhi_acim, act_impedance, act_timerh);
AleX Pelosi43bec422022-04-27 21:59:19 -07002086
2087 return chip->bhi_acim;
2088}
2089
2090/* will return negative if the value is not qualified */
AleX Pelosi43986542022-05-03 15:33:18 -07002091static int max1720x_health_read_impedance(struct max1720x_chip *chip)
Jack Wuecfe7562022-03-17 18:17:53 +08002092{
AleX Pelosi43bec422022-04-27 21:59:19 -07002093 u16 timerh;
Jack Wuecfe7562022-03-17 18:17:53 +08002094 int ret;
2095
Jack Wu94fd2c72022-03-29 20:44:19 +08002096 ret = max1720x_check_impedance(chip, &timerh);
Jack Wuecfe7562022-03-17 18:17:53 +08002097 if (ret < 0)
Jack Wuecfe7562022-03-17 18:17:53 +08002098 return -EINVAL;
2099
AleX Pelosi43bec422022-04-27 21:59:19 -07002100 return max17x0x_read_resistance(chip);
2101}
Jack Wu94fd2c72022-03-29 20:44:19 +08002102
Jenny Hoff9f6a62022-06-30 07:23:42 +00002103/* in hours */
AleX Pelosi43bec422022-04-27 21:59:19 -07002104static int max1720x_get_age(struct max1720x_chip *chip)
2105{
2106 u16 timerh;
2107 int ret;
Jack Wuecfe7562022-03-17 18:17:53 +08002108
AleX Pelosi43bec422022-04-27 21:59:19 -07002109 ret = REGMAP_READ(&chip->regmap, MAX1720X_TIMERH, &timerh);
2110 if (ret < 0 || timerh == 0)
2111 return -ENODATA;
Jack Wuecfe7562022-03-17 18:17:53 +08002112
Jenny Hoff9f6a62022-06-30 07:23:42 +00002113 return reg_to_time_hr(timerh, chip);
Jack Wuecfe7562022-03-17 18:17:53 +08002114}
2115
AleX Pelosi696603c2022-04-30 09:04:04 -07002116static int max1720x_get_fade_rate(struct max1720x_chip *chip)
2117{
AleX Pelosi696603c2022-04-30 09:04:04 -07002118 struct max17x0x_eeprom_history hist = { 0 };
AleX Pelosi9e8633f2022-05-06 18:21:12 +00002119 int ret, ratio, i, fcn_sum = 0;
AleX Pelosi696603c2022-04-30 09:04:04 -07002120 u16 hist_idx;
2121
2122 ret = gbms_storage_read(GBMS_TAG_HCNT, &hist_idx, sizeof(hist_idx));
2123 if (ret < 0) {
Jenny Hoa1e85e92022-05-16 13:36:05 +08002124 dev_err(chip->dev, "failed to get history index (%d)\n", ret);
AleX Pelosi696603c2022-04-30 09:04:04 -07002125 return -EIO;
2126 }
2127
Jenny Hoa1e85e92022-05-16 13:36:05 +08002128 dev_info(chip->dev, "%s: hist_idx=%d\n", __func__, hist_idx);
AleX Pelosi9e8633f2022-05-06 18:21:12 +00002129
2130 if (hist_idx < chip->bhi_fcn_count)
AleX Pelosi696603c2022-04-30 09:04:04 -07002131 return -ENODATA;
2132
AleX Pelosi9e8633f2022-05-06 18:21:12 +00002133 for (i = chip->bhi_fcn_count; i ; i--, hist_idx--) {
2134 ret = gbms_storage_read_data(GBMS_TAG_HIST, &hist,
2135 sizeof(hist), hist_idx);
2136
Jenny Hoa1e85e92022-05-16 13:36:05 +08002137 dev_info(chip->dev, "%s: idx=%d hist.fc=%d (%x) ret=%d\n", __func__,
AleX Pelosi9e8633f2022-05-06 18:21:12 +00002138 hist_idx, hist.fullcapnom, hist.fullcapnom, ret);
2139
2140 if (ret < 0 || hist.fullcapnom == 0x3FF)
AleX Pelosi696603c2022-04-30 09:04:04 -07002141 return -EINVAL;
2142
AleX Pelosi9e8633f2022-05-06 18:21:12 +00002143 /* hist.fullcapnom = fullcapnom * 800 / designcap */
AleX Pelosi696603c2022-04-30 09:04:04 -07002144 fcn_sum += hist.fullcapnom;
2145 }
2146
AleX Pelosi9e8633f2022-05-06 18:21:12 +00002147 /* convert from max17x0x_eeprom_history to percent */
2148 ratio = fcn_sum / (chip->bhi_fcn_count * 8);
2149 if (ratio > 100)
2150 ratio = 100;
2151
2152 return 100 - ratio;
AleX Pelosi696603c2022-04-30 09:04:04 -07002153}
2154
2155
Ken Tsou8acade12020-07-09 03:17:35 +08002156static int max1720x_get_property(struct power_supply *psy,
2157 enum power_supply_property psp,
2158 union power_supply_propval *val)
2159{
2160 struct max1720x_chip *chip = (struct max1720x_chip *)
2161 power_supply_get_drvdata(psy);
2162 struct max17x0x_regmap *map = &chip->regmap;
2163 int rc, err = 0;
2164 u16 data = 0;
2165 int idata;
2166
Jenny Ho2761bd12021-02-23 18:08:08 +08002167 mutex_lock(&chip->model_lock);
2168
Ken Tsou8acade12020-07-09 03:17:35 +08002169 pm_runtime_get_sync(chip->dev);
2170 if (!chip->init_complete || !chip->resume_complete) {
2171 pm_runtime_put_sync(chip->dev);
Jenny Ho2761bd12021-02-23 18:08:08 +08002172 mutex_unlock(&chip->model_lock);
Ken Tsou8acade12020-07-09 03:17:35 +08002173 return -EAGAIN;
2174 }
2175 pm_runtime_put_sync(chip->dev);
2176
Ken Tsou8acade12020-07-09 03:17:35 +08002177 switch (psp) {
2178 case POWER_SUPPLY_PROP_STATUS:
2179 err = max1720x_get_battery_status(chip);
2180 if (err < 0)
2181 break;
2182
2183 /*
2184 * Capacity estimation must run only once.
2185 * NOTE: this is a getter with a side effect
2186 */
2187 val->intval = err;
2188 if (err == POWER_SUPPLY_STATUS_FULL)
2189 batt_ce_start(&chip->cap_estimate,
2190 chip->cap_estimate.cap_tsettle);
Jenny Ho796d0f32021-03-05 06:20:07 +08002191 /* return data ok */
2192 err = 0;
Ken Tsou8acade12020-07-09 03:17:35 +08002193 break;
2194 case POWER_SUPPLY_PROP_HEALTH:
2195 val->intval = max1720x_get_battery_health(chip);
2196 break;
AleX Pelosid2ca4072020-09-03 22:07:27 -07002197 case GBMS_PROP_CAPACITY_RAW:
Ken Tsou8acade12020-07-09 03:17:35 +08002198 err = max1720x_get_capacity_raw(chip, &data);
2199 if (err == 0)
2200 val->intval = (int)data;
2201 break;
2202 case POWER_SUPPLY_PROP_CAPACITY:
2203 idata = max1720x_get_battery_soc(chip);
2204 if (idata < 0) {
2205 err = idata;
2206 break;
2207 }
2208
2209 val->intval = idata;
2210 break;
2211 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
2212 err = max1720x_update_battery_qh_based_capacity(chip);
2213 if (err < 0)
2214 break;
2215
AleX Pelosi962aedf2021-01-07 15:39:43 -08002216 val->intval = reg_to_capacity_uah(chip->current_capacity, chip);
Ken Tsou8acade12020-07-09 03:17:35 +08002217 break;
2218 case POWER_SUPPLY_PROP_CHARGE_FULL:
2219 /*
2220 * Snap charge_full to DESIGNCAP during early charge cycles to
2221 * prevent large fluctuations in FULLCAPNOM. MAX1720X_CYCLES LSB
2222 * is 16%
2223 */
2224 err = max1720x_get_cycle_count(chip);
2225 if (err < 0)
2226 break;
2227
2228 /* err is cycle_count */
2229 if (err <= FULLCAPNOM_STABILIZE_CYCLES)
2230 err = REGMAP_READ(map, MAX1720X_DESIGNCAP, &data);
2231 else
2232 err = REGMAP_READ(map, MAX1720X_FULLCAPNOM, &data);
2233
2234 if (err == 0)
AleX Pelosi962aedf2021-01-07 15:39:43 -08002235 val->intval = reg_to_capacity_uah(data, chip);
Ken Tsou8acade12020-07-09 03:17:35 +08002236 break;
2237 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2238 err = REGMAP_READ(map, MAX1720X_DESIGNCAP, &data);
2239 if (err == 0)
AleX Pelosi962aedf2021-01-07 15:39:43 -08002240 val->intval = reg_to_capacity_uah(data, chip);
Ken Tsou8acade12020-07-09 03:17:35 +08002241 break;
2242 /* current is positive value when flowing to device */
2243 case POWER_SUPPLY_PROP_CURRENT_AVG:
2244 err = max17x0x_reg_read(map, MAX17X0X_TAG_avgc, &data);
2245 if (err == 0)
2246 val->intval = -reg_to_micro_amp(data, chip->RSense);
2247 break;
2248 /* current is positive value when flowing to device */
2249 case POWER_SUPPLY_PROP_CURRENT_NOW:
2250 err = max17x0x_reg_read(map, MAX17X0X_TAG_curr, &data);
2251 if (err == 0)
2252 val->intval = -reg_to_micro_amp(data, chip->RSense);
2253 break;
2254 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2255 err = max1720x_get_cycle_count(chip);
2256 if (err < 0)
2257 break;
2258 /* err is cycle_count */
2259 val->intval = err;
Jenny Ho796d0f32021-03-05 06:20:07 +08002260 /* return data ok */
2261 err = 0;
Ken Tsou8acade12020-07-09 03:17:35 +08002262 break;
2263 case POWER_SUPPLY_PROP_PRESENT:
Jenny Hoc1cdb8b2021-08-12 12:29:25 +08002264
Jack Wue3ccc812022-08-30 23:04:57 +08002265 if (chip->fake_battery != -1) {
AleX Pelosi8c5fa772020-10-03 13:36:56 -07002266 val->intval = chip->fake_battery;
Jack Wue3ccc812022-08-30 23:04:57 +08002267 } else if (chip->gauge_type == -1) {
2268 val->intval = 0;
Ken Tsou8acade12020-07-09 03:17:35 +08002269 } else {
AleX Pelosid7c3e632021-09-17 16:33:48 -07002270
Ken Tsou8acade12020-07-09 03:17:35 +08002271 err = REGMAP_READ(map, MAX1720X_STATUS, &data);
2272 if (err < 0)
2273 break;
2274
2275 /* BST is 0 when the battery is present */
AleX Pelosid7c3e632021-09-17 16:33:48 -07002276 val->intval = !(data & MAX1720X_STATUS_BST);
2277 if (!val->intval)
2278 break;
Jenny Hod4721532021-08-12 12:29:25 +08002279
AleX Pelosid7c3e632021-09-17 16:33:48 -07002280 /* chip->por prevent garbage in cycle count */
Jenny Ho6a391fd2022-08-10 23:33:14 +00002281 chip->por = (data & MAX1720X_STATUS_POR) != 0;
2282 if (chip->por && chip->model_ok &&
2283 chip->model_reload != MAX_M5_LOAD_MODEL_REQUEST) {
AleX Pelosid7c3e632021-09-17 16:33:48 -07002284 /* trigger reload model and clear of POR */
Jenny Ho27accd52021-12-14 11:05:15 +08002285 mutex_unlock(&chip->model_lock);
Jenny Hod4721532021-08-12 12:29:25 +08002286 max1720x_fg_irq_thread_fn(-1, chip);
Jenny Ho27accd52021-12-14 11:05:15 +08002287 return err;
Jenny Hod4721532021-08-12 12:29:25 +08002288 }
Ken Tsou8acade12020-07-09 03:17:35 +08002289 }
2290 break;
Ken Tsou8acade12020-07-09 03:17:35 +08002291 case POWER_SUPPLY_PROP_TEMP:
2292 err = max17x0x_reg_read(map, MAX17X0X_TAG_temp, &data);
2293 if (err < 0)
2294 break;
2295
2296 val->intval = reg_to_deci_deg_cel(data);
2297 max1720x_handle_update_nconvgcfg(chip, val->intval);
Jenny Ho80a583b2021-11-15 01:46:25 +08002298 max1720x_handle_update_filtercfg(chip, val->intval);
Ken Tsou8acade12020-07-09 03:17:35 +08002299 max1720x_handle_update_empty_voltage(chip, val->intval);
2300 break;
2301 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
2302 err = REGMAP_READ(map, MAX1720X_TTE, &data);
2303 if (err == 0)
2304 val->intval = reg_to_seconds(data);
2305 break;
2306 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
2307 err = REGMAP_READ(map, MAX1720X_TTF, &data);
2308 if (err == 0)
2309 val->intval = reg_to_seconds(data);
2310 break;
Jenny Ho5f6475b2021-06-08 16:50:37 +08002311 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
2312 val->intval = -1;
2313 break;
Ken Tsou8acade12020-07-09 03:17:35 +08002314 case POWER_SUPPLY_PROP_VOLTAGE_AVG:
2315 err = REGMAP_READ(map, MAX1720X_AVGVCELL, &data);
2316 if (err == 0)
2317 val->intval = reg_to_micro_volt(data);
2318 break;
2319 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2320 /* LSB: 20mV */
2321 err = max17x0x_reg_read(map, MAX17X0X_TAG_mmdv, &data);
2322 if (err == 0)
2323 val->intval = ((data >> 8) & 0xFF) * 20000;
2324 break;
2325 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2326 /* LSB: 20mV */
2327 err = max17x0x_reg_read(map, MAX17X0X_TAG_mmdv, &data);
2328 if (err == 0)
2329 val->intval = (data & 0xFF) * 20000;
2330 break;
2331 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2332 err = max17x0x_reg_read(map, MAX17X0X_TAG_vcel, &data);
2333 if (err == 0)
2334 val->intval = reg_to_micro_volt(data);
2335 break;
2336 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2337 rc = max17x0x_reg_read(map, MAX17X0X_TAG_vfocv, &data);
2338 if (rc == -EINVAL) {
2339 val->intval = -1;
2340 break;
2341 }
2342 val->intval = reg_to_micro_volt(data);
2343 break;
2344 case POWER_SUPPLY_PROP_TECHNOLOGY:
2345 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2346 break;
2347 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
2348 val->strval = chip->serial_number;
2349 break;
Jack Wuecfe7562022-03-17 18:17:53 +08002350 case GBMS_PROP_HEALTH_ACT_IMPEDANCE:
AleX Pelosi43986542022-05-03 15:33:18 -07002351 val->intval = max1720x_health_get_ai(chip);
AleX Pelosi43bec422022-04-27 21:59:19 -07002352 break;
2353 case GBMS_PROP_HEALTH_IMPEDANCE:
AleX Pelosi43986542022-05-03 15:33:18 -07002354 val->intval = max1720x_health_read_impedance(chip);
2355 break;
2356 case GBMS_PROP_RESISTANCE:
2357 val->intval = max17x0x_read_resistance(chip);
2358 break;
2359 case GBMS_PROP_RESISTANCE_RAW:
2360 val->intval = max17x0x_read_resistance_raw(chip);
2361 break;
2362 case GBMS_PROP_RESISTANCE_AVG:
2363 val->intval = max17x0x_read_resistance_avg(chip);
Jack Wuecfe7562022-03-17 18:17:53 +08002364 break;
AleX Pelosi43bec422022-04-27 21:59:19 -07002365 case GBMS_PROP_BATTERY_AGE:
2366 val->intval = max1720x_get_age(chip);
2367 break;
AleX Pelosi696603c2022-04-30 09:04:04 -07002368 case GBMS_PROP_CHARGE_FULL_ESTIMATE:
AleX Pelosi43bec422022-04-27 21:59:19 -07002369 val->intval = batt_ce_full_estimate(&chip->cap_estimate);
2370 break;
AleX Pelosi696603c2022-04-30 09:04:04 -07002371 case GBMS_PROP_CAPACITY_FADE_RATE:
2372 val->intval = max1720x_get_fade_rate(chip);
2373 break;
Ken Tsou8acade12020-07-09 03:17:35 +08002374 default:
2375 err = -EINVAL;
2376 break;
2377 }
2378
2379 if (err < 0)
2380 pr_debug("error %d reading prop %d\n", err, psp);
2381
2382 mutex_unlock(&chip->model_lock);
2383 return err;
2384}
2385
AleX Pelosic1cd4752022-05-04 02:15:02 -07002386/* needs mutex_lock(&chip->model_lock); */
2387static int max1720x_health_update_ai(struct max1720x_chip *chip, int impedance)
2388{
2389 const u16 act_impedance = impedance / 100;
2390 unsigned int rcell = 0xffff;
2391 u16 timerh = 0xffff;
2392 int ret;
2393
2394 if (impedance) {
2395
2396 /* mOhms to reg */
2397 rcell = (impedance * 4096) / (1000 * chip->RSense);
2398 if (rcell > 0xffff) {
2399 pr_err("value=%d, rcell=%d out of bounds\n", impedance, rcell);
2400 return -ERANGE;
2401 }
2402
2403 ret = REGMAP_READ(&chip->regmap, MAX1720X_TIMERH, &timerh);
2404 if (ret < 0 || timerh == 0)
2405 return -EIO;
2406 }
2407
2408 ret = max1720x_health_write_ai(act_impedance, timerh);
2409 if (ret == 0)
2410 chip->bhi_acim = 0;
2411
2412 return ret;
2413}
2414
2415
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002416static void max1720x_fixup_capacity(struct max1720x_chip *chip, int plugged)
2417{
2418 struct max1720x_drift_data *ddata = &chip->drift_data;
Jenny Hoe63ab0e2021-01-22 16:43:08 +08002419 int ret, cycle_count, cap_lsb;
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002420 u16 data16;
2421
2422 /* do not execute when POR is set */
2423 ret = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &data16);
2424 if (ret < 0 || data16 & MAX1720X_STATUS_POR)
2425 return;
2426
2427 /* capacity outliers: fix rcomp0, tempco */
2428 ret = max1720x_fixup_comp(ddata, &chip->regmap, plugged);
2429 if (ret > 0) {
2430 chip->comp_update_count += 1;
2431
2432 data16 = chip->comp_update_count;
2433 ret = gbms_storage_write(GBMS_TAG_CMPC, &data16, sizeof(data16));
2434 if (ret < 0)
2435 dev_err(chip->dev, "update comp stats (%d)\n", ret);
2436 }
2437
2438 cycle_count = max1720x_get_cycle_count(chip);
2439 if (cycle_count < 0) {
2440 dev_err(chip->dev, "cannot read cycle_count (%d)\n",
2441 cycle_count);
2442 return;
2443 }
2444
2445 /* capacity outliers: fix capacity */
Jenny Hoe63ab0e2021-01-22 16:43:08 +08002446 cap_lsb = max_m5_cap_lsb(chip->model_data);
2447 ret = max1720x_fixup_dxacc(ddata, &chip->regmap, cycle_count, plugged, cap_lsb);
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002448 if (ret > 0) {
2449 chip->dxacc_update_count += 1;
2450
2451 data16 = chip->dxacc_update_count;
2452 ret = gbms_storage_write(GBMS_TAG_DXAC, &data16, sizeof(data16));
2453 if (ret < 0)
2454 dev_err(chip->dev, "update cap stats (%d)\n", ret);
2455 }
2456
2457}
2458
Ken Tsou8acade12020-07-09 03:17:35 +08002459static int max1720x_set_property(struct power_supply *psy,
2460 enum power_supply_property psp,
2461 const union power_supply_propval *val)
2462{
2463 struct max1720x_chip *chip = (struct max1720x_chip *)
2464 power_supply_get_drvdata(psy);
2465 struct gbatt_capacity_estimation *ce = &chip->cap_estimate;
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002466 int delay_ms = 0;
Ken Tsou8acade12020-07-09 03:17:35 +08002467 int rc = 0;
Ken Tsou8acade12020-07-09 03:17:35 +08002468
Jenny Hofbc5dd32021-03-04 16:01:02 +08002469 mutex_lock(&chip->model_lock);
Ken Tsou8acade12020-07-09 03:17:35 +08002470 pm_runtime_get_sync(chip->dev);
2471 if (!chip->init_complete || !chip->resume_complete) {
2472 pm_runtime_put_sync(chip->dev);
Jenny Hofbc5dd32021-03-04 16:01:02 +08002473 mutex_unlock(&chip->model_lock);
Ken Tsou8acade12020-07-09 03:17:35 +08002474 return -EAGAIN;
2475 }
2476 pm_runtime_put_sync(chip->dev);
Jenny Hofbc5dd32021-03-04 16:01:02 +08002477 mutex_unlock(&chip->model_lock);
Ken Tsou8acade12020-07-09 03:17:35 +08002478
2479 switch (psp) {
AleX Pelosid2ca4072020-09-03 22:07:27 -07002480 case GBMS_PROP_BATT_CE_CTRL:
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002481
Ken Tsou8acade12020-07-09 03:17:35 +08002482 mutex_lock(&ce->batt_ce_lock);
Jenny Ho5f6475b2021-06-08 16:50:37 +08002483
2484 if (chip->gauge_type == MAX_M5_GAUGE_TYPE &&
2485 !chip->model_state_valid) {
2486 mutex_unlock(&ce->batt_ce_lock);
2487 return -EAGAIN;
2488 }
2489
Ken Tsou8acade12020-07-09 03:17:35 +08002490 if (val->intval) {
2491
2492 if (!ce->cable_in) {
2493 rc = batt_ce_init(ce, chip);
2494 ce->cable_in = (rc == 0);
2495 }
2496
2497 } else if (ce->cable_in) {
Ken Tsou8acade12020-07-09 03:17:35 +08002498 if (ce->estimate_state == ESTIMATE_PENDING)
2499 cancel_delayed_work_sync(&ce->settle_timer);
2500
2501 /* race with batt_ce_capacityfiltered_work() */
2502 batt_ce_stop_estimation(ce, ESTIMATE_NONE);
2503 batt_ce_dump_data(ce, chip->ce_log);
2504 ce->cable_in = false;
2505 }
2506 mutex_unlock(&ce->batt_ce_lock);
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002507
2508
2509 /* check cycle count, save state, check drift if needed */
2510 delay_ms = max1720x_check_drift_delay(&chip->drift_data);
Jenny Ho5f6475b2021-06-08 16:50:37 +08002511 mod_delayed_work(system_wq, &chip->model_work,
2512 msecs_to_jiffies(delay_ms));
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002513
Ken Tsou8acade12020-07-09 03:17:35 +08002514 break;
AleX Pelosic1cd4752022-05-04 02:15:02 -07002515 case GBMS_PROP_HEALTH_ACT_IMPEDANCE:
2516 mutex_lock(&chip->model_lock);
2517 rc = max1720x_health_update_ai(chip, val->intval);
2518 mutex_unlock(&chip->model_lock);
2519 break;
Ken Tsou8acade12020-07-09 03:17:35 +08002520 default:
2521 return -EINVAL;
2522 }
2523
2524 if (rc < 0)
2525 return rc;
2526
2527 return 0;
2528}
2529
2530static int max1720x_property_is_writeable(struct power_supply *psy,
2531 enum power_supply_property psp)
2532{
2533 switch (psp) {
AleX Pelosid2ca4072020-09-03 22:07:27 -07002534 case GBMS_PROP_BATT_CE_CTRL:
AleX Pelosic1cd4752022-05-04 02:15:02 -07002535 case GBMS_PROP_HEALTH_ACT_IMPEDANCE:
Ken Tsou8acade12020-07-09 03:17:35 +08002536 return 1;
2537 default:
2538 break;
2539 }
2540
2541 return 0;
2542}
2543
Jenny Ho5381a6f2021-08-11 14:34:45 +08002544static int max1720x_monitor_log_data(struct max1720x_chip *chip)
2545{
2546 u16 data, repsoc, vfsoc, avcap, repcap, fullcap, fullcaprep;
2547 u16 fullcapnom, qh0, qh, dqacc, dpacc, qresidual, fstat;
Jenny Ho39b2def2022-03-02 18:18:13 +08002548 u16 learncfg, tempco;
Jenny Hod2a378b2022-04-26 10:47:39 +08002549 int ret = 0, charge_counter = -1;
Jenny Ho5381a6f2021-08-11 14:34:45 +08002550
2551 ret = REGMAP_READ(&chip->regmap, MAX1720X_REPSOC, &data);
2552 if (ret < 0)
2553 return ret;
2554
2555 repsoc = (data >> 8) & 0x00FF;
2556 if (repsoc == chip->pre_repsoc)
2557 return ret;
2558
2559 ret = REGMAP_READ(&chip->regmap, MAX1720X_VFSOC, &vfsoc);
2560 if (ret < 0)
2561 return ret;
2562
2563 ret = REGMAP_READ(&chip->regmap, MAX1720X_AVCAP, &avcap);
2564 if (ret < 0)
2565 return ret;
2566
2567 ret = REGMAP_READ(&chip->regmap, MAX1720X_REPCAP, &repcap);
2568 if (ret < 0)
2569 return ret;
2570
2571 ret = REGMAP_READ(&chip->regmap, MAX1720X_FULLCAP, &fullcap);
2572 if (ret < 0)
2573 return ret;
2574
2575 ret = REGMAP_READ(&chip->regmap, MAX1720X_FULLCAPREP, &fullcaprep);
2576 if (ret < 0)
2577 return ret;
2578
2579 ret = REGMAP_READ(&chip->regmap, MAX1720X_FULLCAPNOM, &fullcapnom);
2580 if (ret < 0)
2581 return ret;
2582
2583 ret = REGMAP_READ(&chip->regmap, MAX1720X_QH0, &qh0);
2584 if (ret < 0)
2585 return ret;
2586
2587 ret = REGMAP_READ(&chip->regmap, MAX1720X_QH, &qh);
2588 if (ret < 0)
2589 return ret;
2590
2591 ret = REGMAP_READ(&chip->regmap, MAX1720X_DQACC, &dqacc);
2592 if (ret < 0)
2593 return ret;
2594
2595 ret = REGMAP_READ(&chip->regmap, MAX1720X_DPACC, &dpacc);
2596 if (ret < 0)
2597 return ret;
2598
2599 ret = REGMAP_READ(&chip->regmap, MAX1720X_QRESIDUAL, &qresidual);
2600 if (ret < 0)
2601 return ret;
2602
2603 ret = REGMAP_READ(&chip->regmap, MAX1720X_FSTAT, &fstat);
2604 if (ret < 0)
2605 return ret;
2606
Jenny Ho39b2def2022-03-02 18:18:13 +08002607 ret = REGMAP_READ(&chip->regmap, MAX1720X_LEARNCFG, &learncfg);
2608 if (ret < 0)
2609 return ret;
2610
2611 ret = REGMAP_READ(&chip->regmap, MAX1720X_TEMPCO, &tempco);
2612 if (ret < 0)
2613 return ret;
2614
Jenny Hod2a378b2022-04-26 10:47:39 +08002615 ret = max1720x_update_battery_qh_based_capacity(chip);
2616 if (ret == 0)
2617 charge_counter = reg_to_capacity_uah(chip->current_capacity, chip);
2618
Jenny Ho71413292022-01-19 16:52:47 +08002619 gbms_logbuffer_prlog(chip->monitor_log, LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
2620 "%s %02X:%04X %02X:%04X %02X:%04X %02X:%04X %02X:%04X"
2621 " %02X:%04X %02X:%04X %02X:%04X %02X:%04X %02X:%04X"
Jenny Ho39b2def2022-03-02 18:18:13 +08002622 " %02X:%04X %02X:%04X %02X:%04X %02X:%04X %02X:%04X CC:%d",
Jenny Hoa1e85e92022-05-16 13:36:05 +08002623 chip->max1720x_psy_desc.name, MAX1720X_REPSOC, data, MAX1720X_VFSOC,
2624 vfsoc, MAX1720X_AVCAP, avcap, MAX1720X_REPCAP, repcap,
Jenny Ho71413292022-01-19 16:52:47 +08002625 MAX1720X_FULLCAP, fullcap, MAX1720X_FULLCAPREP, fullcaprep,
2626 MAX1720X_FULLCAPNOM, fullcapnom, MAX1720X_QH0, qh0,
2627 MAX1720X_QH, qh, MAX1720X_DQACC, dqacc, MAX1720X_DPACC, dpacc,
Jenny Hod2a378b2022-04-26 10:47:39 +08002628 MAX1720X_QRESIDUAL, qresidual, MAX1720X_FSTAT, fstat,
Jenny Ho39b2def2022-03-02 18:18:13 +08002629 MAX1720X_LEARNCFG, learncfg, MAX1720X_TEMPCO, tempco,
Jenny Hod2a378b2022-04-26 10:47:39 +08002630 charge_counter);
Jenny Ho5381a6f2021-08-11 14:34:45 +08002631
2632 chip->pre_repsoc = repsoc;
2633
2634 return ret;
2635}
2636
Ken Tsou8acade12020-07-09 03:17:35 +08002637/*
2638 * A fuel gauge reset resets only the fuel gauge operation without resetting IC
2639 * hardware. This is useful for testing different configurations without writing
2640 * nonvolatile memory.
2641 * TODO: add a lock around fg_reset to prevent SW from accessing the gauge until
2642 * the delay for volatile register access (rset->map[2]) expires. Need a lock
2643 * only if using this after _init()
2644 */
2645static int max17x0x_fg_reset(struct max1720x_chip *chip)
2646{
2647 const struct max17x0x_reg *rset;
2648 bool done = false;
2649 int err;
2650
2651 rset = max17x0x_find_by_tag(&chip->regmap_nvram, MAX17X0X_TAG_rset);
2652 if (!rset)
2653 return -EINVAL;
2654
2655 dev_info(chip->dev, "FG_RESET addr=%x value=%x delay=%d\n",
2656 rset->map16[0], rset->map16[1], rset->map16[2]);
2657
2658 err = REGMAP_WRITE(&chip->regmap, rset->map16[0], rset->map16[1]);
2659 if (err < 0) {
2660 dev_err(chip->dev, "FG_RESET error writing Config2 (%d)\n",
2661 err);
2662 } else {
2663 int loops = 10; /* 10 * MAX17X0X_TPOR_MS = 1.5 secs */
2664 u16 cfg2 = 0;
2665
2666 for ( ; loops ; loops--) {
2667 msleep(MAX17X0X_TPOR_MS);
2668
2669 err = REGMAP_READ(&chip->regmap, rset->map16[0], &cfg2);
2670 done = (err == 0) && !(cfg2 & rset->map16[1]);
2671 if (done) {
2672 msleep(rset->map16[2]);
2673 break;
2674 }
2675 }
2676
2677 if (!done)
2678 dev_err(chip->dev, "FG_RESET error rst not clearing\n");
2679 else
2680 dev_info(chip->dev, "FG_RESET cleared in %dms\n",
2681 loops * MAX17X0X_TPOR_MS + rset->map16[2]);
2682
2683 }
2684
2685 return 0;
2686}
2687
AleX Pelosi670001c2021-06-28 13:10:08 -07002688int max17x0x_sw_reset(struct i2c_client *client)
2689{
2690 struct max1720x_chip *chip = i2c_get_clientdata(client);
2691
2692 if (!chip)
2693 return -ENODEV;
2694
2695 return max17x0x_fg_reset(chip);
2696}
2697EXPORT_SYMBOL_GPL(max17x0x_sw_reset);
2698
Ken Tsou8acade12020-07-09 03:17:35 +08002699/*
2700 * A full reset restores the ICs to their power-up state the same as if power
2701 * had been cycled.
2702 */
2703static int max1720x_full_reset(struct max1720x_chip *chip)
2704{
2705 if (chip->gauge_type == MAX1730X_GAUGE_TYPE) {
2706 /*
2707 * a full (hw) reset on max1730x cause charge and discharge FET
2708 * to toggle and the device will lose power. Will need to
2709 * connect the device to a charger to get max1730x firmware to
2710 * start and max1730x to close the FETs. Never send a HW reset
2711 * to a 1730x while in system...
2712 */
2713 dev_warn(chip->dev, "ignore full reset of fuel gauge\n");
2714 return 0;
2715 }
2716
2717 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
2718 MAX1720X_COMMAND_HARDWARE_RESET);
2719
2720 msleep(MAX17X0X_TPOR_MS);
2721
2722 return 0;
2723}
2724
2725#define IRQ_STORM_TRIGGER_SECONDS 60
2726#define IRQ_STORM_TRIGGER_MAX_COUNTS 50
2727static bool max1720x_fg_irq_storm_check(struct max1720x_chip *chip)
2728{
2729 int now_time = 0, interval_time, irq_cnt;
2730 bool storm = false;
2731 static int stime;
2732
2733 chip->icnt++;
2734
2735 now_time = div_u64(ktime_to_ns(ktime_get_boottime()), NSEC_PER_SEC);
2736 if (now_time < IRQ_STORM_TRIGGER_SECONDS) {
2737 stime = now_time;
2738 chip->icnt = 0;
2739 }
2740
2741 interval_time = now_time - stime;
2742 if (interval_time > IRQ_STORM_TRIGGER_SECONDS) {
2743 irq_cnt = chip->icnt * 100;
2744 irq_cnt /= (interval_time * 100 / IRQ_STORM_TRIGGER_SECONDS);
2745
2746 storm = irq_cnt > IRQ_STORM_TRIGGER_MAX_COUNTS;
2747 if (!storm) {
2748 stime = now_time;
2749 chip->icnt = 0;
2750 }
2751 }
2752
2753 return storm;
2754}
2755
2756static irqreturn_t max1720x_fg_irq_thread_fn(int irq, void *obj)
2757{
2758 struct max1720x_chip *chip = (struct max1720x_chip *)obj;
2759 u16 fg_status, fg_status_clr;
2760 bool storm = false;
2761 int err = 0;
2762
AleX Pelosiffcc7ec2020-09-08 17:05:01 -07002763 if (!chip || (irq != -1 && irq != chip->primary->irq)) {
Ken Tsou8acade12020-07-09 03:17:35 +08002764 WARN_ON_ONCE(1);
2765 return IRQ_NONE;
2766 }
2767
2768 if (chip->gauge_type == -1)
2769 return IRQ_NONE;
2770
2771 pm_runtime_get_sync(chip->dev);
2772 if (!chip->init_complete || !chip->resume_complete) {
Wasb Liudc49a932022-03-01 14:44:17 +08002773 if (chip->init_complete && !chip->irq_disabled) {
2774 chip->irq_disabled = true;
2775 disable_irq_nosync(chip->primary->irq);
2776 }
Ken Tsou8acade12020-07-09 03:17:35 +08002777 pm_runtime_put_sync(chip->dev);
Jenny Hoe625e1a2021-03-02 06:41:59 +08002778 return IRQ_HANDLED;
Ken Tsou8acade12020-07-09 03:17:35 +08002779 }
2780
2781 pm_runtime_put_sync(chip->dev);
2782
2783 err = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &fg_status);
2784 if (err)
2785 return IRQ_NONE;
2786
2787 /* disable storm check and spurius with shared interrupts */
2788 if (!chip->irq_shared) {
2789
2790 storm = max1720x_fg_irq_storm_check(chip);
2791 if (storm) {
2792 u16 fg_alarm = 0;
2793
2794 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
2795 err = REGMAP_READ(&chip->regmap, MAX1720X_ALARM,
2796 &fg_alarm);
2797
AleX Pelosi5077fc52020-09-10 21:44:48 -07002798 dev_warn(chip->dev, "sts:%04x, alarm:%04x, cnt:%lu err=%d\n",
Ken Tsou8acade12020-07-09 03:17:35 +08002799 fg_status, fg_alarm, chip->icnt, err);
2800 }
2801
2802 if (fg_status == 0) {
2803 chip->debug_irq_none_cnt++;
2804 pr_debug("spurius: fg_status=0 cnt=%d\n",
2805 chip->debug_irq_none_cnt);
2806 /* rate limit spurius interrupts */
2807 msleep(MAX1720X_TICLR_MS);
2808 return IRQ_HANDLED;
2809 }
2810 } else if (fg_status == 0) {
2811 /*
2812 * Disable rate limiting for when interrupt is shared.
2813 * NOTE: this might need to be re-evaluated at some later point
2814 */
2815 return IRQ_NONE;
2816 }
2817
2818 /* only used to report health */
2819 chip->health_status |= fg_status;
2820
2821 /*
2822 * write 0 to clear will loose interrupts when we don't write 1 to the
2823 * bits that are not set. Just inverting fg_status cause an interrupt
2824 * storm, only setting the bits marked as "host must clear" in the DS
2825 * seems to work eg:
2826 *
2827 * fg_status_clr = fg_status
2828 * fg_status_clr |= MAX1720X_STATUS_POR | MAX1720X_STATUS_DSOCI
2829 * | MAX1720X_STATUS_BI;
2830 *
2831 * If the above logic is sound, we probably need to set also the bits
2832 * that config mark as "host must clear". Maxim to confirm.
2833 */
2834 fg_status_clr = fg_status;
2835
2836 if (fg_status & MAX1720X_STATUS_POR) {
Jenny Ho6a391fd2022-08-10 23:33:14 +00002837 mutex_lock(&chip->model_lock);
2838 chip->por = true;
2839 dev_warn(chip->dev, "POR is set(%04x), model reload:%d\n",
2840 fg_status, chip->model_reload);
Jenny Ho3691c562022-07-20 04:37:24 +00002841 /* trigger model load if not on-going */
2842 if (chip->model_reload != MAX_M5_LOAD_MODEL_REQUEST) {
Jenny Ho3691c562022-07-20 04:37:24 +00002843 err = max1720x_model_reload(chip, true);
2844 if (err < 0)
2845 fg_status_clr &= ~MAX1720X_STATUS_POR;
Jenny Ho3691c562022-07-20 04:37:24 +00002846 }
Jenny Ho6a391fd2022-08-10 23:33:14 +00002847 mutex_unlock(&chip->model_lock);
Ken Tsou8acade12020-07-09 03:17:35 +08002848 }
2849
2850 if (fg_status & MAX1720X_STATUS_IMN)
2851 pr_debug("IMN is set\n");
2852
2853 if (fg_status & MAX1720X_STATUS_BST)
2854 pr_debug("BST is set\n");
2855
2856 if (fg_status & MAX1720X_STATUS_IMX)
2857 pr_debug("IMX is set\n");
2858
2859 if (fg_status & MAX1720X_STATUS_DSOCI) {
2860 fg_status_clr &= ~MAX1720X_STATUS_DSOCI;
2861 pr_debug("DSOCI is set\n");
2862 }
2863 if (fg_status & MAX1720X_STATUS_VMN) {
2864 if (chip->RConfig & MAX1720X_CONFIG_VS)
2865 fg_status_clr &= ~MAX1720X_STATUS_VMN;
2866 pr_debug("VMN is set\n");
2867 }
2868 if (fg_status & MAX1720X_STATUS_TMN) {
2869 if (chip->RConfig & MAX1720X_CONFIG_TS)
2870 fg_status_clr &= ~MAX1720X_STATUS_TMN;
2871 pr_debug("TMN is set\n");
2872 }
2873 if (fg_status & MAX1720X_STATUS_SMN) {
2874 if (chip->RConfig & MAX1720X_CONFIG_SS)
2875 fg_status_clr &= ~MAX1720X_STATUS_SMN;
2876 pr_debug("SMN is set\n");
2877 }
2878 if (fg_status & MAX1720X_STATUS_BI)
2879 pr_debug("BI is set\n");
2880
2881 if (fg_status & MAX1720X_STATUS_VMX) {
2882 if (chip->RConfig & MAX1720X_CONFIG_VS)
2883 fg_status_clr &= ~MAX1720X_STATUS_VMX;
2884 pr_debug("VMX is set\n");
2885 }
2886 if (fg_status & MAX1720X_STATUS_TMX) {
2887 if (chip->RConfig & MAX1720X_CONFIG_TS)
2888 fg_status_clr &= ~MAX1720X_STATUS_TMX;
2889 pr_debug("TMX is set\n");
2890 }
2891 if (fg_status & MAX1720X_STATUS_SMX) {
2892 if (chip->RConfig & MAX1720X_CONFIG_SS)
2893 fg_status_clr &= ~MAX1720X_STATUS_SMX;
2894 pr_debug("SMX is set\n");
2895 }
2896
2897 if (fg_status & MAX1720X_STATUS_BR)
2898 pr_debug("BR is set\n");
2899
2900 /* NOTE: should always clear everything even if we lose state */
2901 REGMAP_WRITE(&chip->regmap, MAX1720X_STATUS, fg_status_clr);
2902
AleX Pelosi9f326fb2020-10-27 01:50:47 -07002903 /* SOC interrupts need to go through all the time */
2904 if (fg_status & MAX1720X_STATUS_DSOCI) {
2905 const bool plugged = chip->cap_estimate.cable_in;
2906
2907 if (max1720x_check_drift_on_soc(&chip->drift_data))
2908 max1720x_fixup_capacity(chip, plugged);
2909
2910 if (storm)
2911 pr_debug("Force power_supply_change in storm\n");
Jenny Ho5381a6f2021-08-11 14:34:45 +08002912 else
2913 max1720x_monitor_log_data(chip);
2914
Ken Tsou8acade12020-07-09 03:17:35 +08002915 storm = false;
2916 }
2917
2918 if (chip->psy && !storm)
2919 power_supply_changed(chip->psy);
2920
2921 /*
2922 * oneshot w/o filter will unmask on return but gauge will take up
2923 * to 351 ms to clear ALRM1.
2924 * NOTE: can do this masking on gauge side (Config, 0x1D) and using a
2925 * workthread to re-enable.
2926 */
AleX Pelosiffcc7ec2020-09-08 17:05:01 -07002927 if (irq != -1)
2928 msleep(MAX1720X_TICLR_MS);
2929
Ken Tsou8acade12020-07-09 03:17:35 +08002930
2931 return IRQ_HANDLED;
2932}
2933
2934/* used to find batt_node and chemistry dependent FG overrides */
2935static int max1720x_read_batt_id(int *batt_id, const struct max1720x_chip *chip)
2936{
2937 bool defer;
2938 int rc = 0;
2939 struct device_node *node = chip->dev->of_node;
2940 u32 temp_id = 0;
2941
2942 /* force the value in kohm */
2943 rc = of_property_read_u32(node, "maxim,force-batt-id", &temp_id);
2944 if (rc == 0) {
2945 dev_warn(chip->dev, "forcing battery RID %d\n", temp_id);
2946 *batt_id = temp_id;
2947 return 0;
2948 }
2949
2950 /* return the value in kohm */
2951 rc = gbms_storage_read(GBMS_TAG_BRID, &temp_id, sizeof(temp_id));
2952 defer = (rc == -EPROBE_DEFER) ||
2953 (rc == -EINVAL) ||
2954 ((rc == 0) && (temp_id == -EINVAL));
2955 if (defer)
2956 return -EPROBE_DEFER;
2957
2958 if (rc < 0) {
2959 dev_err(chip->dev, "failed to get batt-id rc=%d\n", rc);
2960 *batt_id = -1;
Jenny Ho29d7efa2021-05-27 14:46:44 +08002961 return -EPROBE_DEFER;
Ken Tsou8acade12020-07-09 03:17:35 +08002962 }
2963
2964 *batt_id = temp_id;
2965 return 0;
2966}
2967
AleX Pelosi962aedf2021-01-07 15:39:43 -08002968/* */
AleX Pelosifed7fb12020-11-10 01:22:22 -08002969static struct device_node *max1720x_find_batt_node(struct max1720x_chip *chip)
Ken Tsou8acade12020-07-09 03:17:35 +08002970{
AleX Pelosifed7fb12020-11-10 01:22:22 -08002971 const int batt_id = chip->batt_id;
2972 const struct device *dev = chip->dev;
Ken Tsou8acade12020-07-09 03:17:35 +08002973 struct device_node *config_node, *child_node;
AleX Pelosi962aedf2021-01-07 15:39:43 -08002974 u32 batt_id_range = 20, batt_id_kohm;
AleX Pelosifed7fb12020-11-10 01:22:22 -08002975 int ret;
Ken Tsou8acade12020-07-09 03:17:35 +08002976
AleX Pelosifed7fb12020-11-10 01:22:22 -08002977 config_node = of_find_node_by_name(dev->of_node, "maxim,config");
Ken Tsou8acade12020-07-09 03:17:35 +08002978 if (!config_node) {
2979 dev_warn(dev, "Failed to find maxim,config setting\n");
2980 return NULL;
2981 }
2982
AleX Pelosifed7fb12020-11-10 01:22:22 -08002983 ret = of_property_read_u32(dev->of_node, "maxim,batt-id-range-pct",
2984 &batt_id_range);
2985 if (ret && ret == -EINVAL)
2986 dev_warn(dev, "failed to read maxim,batt-id-range-pct\n");
2987
Ken Tsou8acade12020-07-09 03:17:35 +08002988 for_each_child_of_node(config_node, child_node) {
2989 ret = of_property_read_u32(child_node, "maxim,batt-id-kohm",
2990 &batt_id_kohm);
2991 if (ret != 0)
2992 continue;
AleX Pelosifed7fb12020-11-10 01:22:22 -08002993
AleX Pelosi962aedf2021-01-07 15:39:43 -08002994 /* only look for matching algo_ver if set */
2995 if (chip->drift_data.algo_ver != MAX1720X_DA_VER_NONE) {
2996 u32 algo_ver;
2997
2998 ret = of_property_read_u32(child_node,
2999 "maxim,algo-version",
3000 &algo_ver);
3001 if (ret == 0 && chip->drift_data.algo_ver != algo_ver)
3002 continue;
3003 }
3004
Ken Tsou8acade12020-07-09 03:17:35 +08003005 if (!batt_id_range && batt_id == batt_id_kohm)
3006 return child_node;
3007 if ((batt_id < (batt_id_kohm * (100 + batt_id_range) / 100)) &&
3008 (batt_id > (batt_id_kohm * (100 - batt_id_range) / 100)))
3009 return child_node;
3010 }
3011
3012 return NULL;
3013}
3014
3015static int max17x0x_apply_regval_shadow(struct max1720x_chip *chip,
3016 struct device_node *node,
3017 struct max17x0x_cache_data *nRAM,
3018 int nb)
3019{
3020 u16 *regs;
3021 int ret, i;
3022 const char *propname = (chip->gauge_type == MAX1730X_GAUGE_TYPE) ?
3023 "maxim,n_regval_1730x" : "maxim,n_regval_1720x";
3024
3025 if (!node || nb <= 0)
3026 return 0;
3027
3028 if (nb & 1) {
3029 dev_warn(chip->dev, "%s %s u16 elems count is not even: %d\n",
3030 node->name, propname, nb);
3031 return -EINVAL;
3032 }
3033
3034 regs = batt_alloc_array(nb, sizeof(u16));
3035 if (!regs)
3036 return -ENOMEM;
3037
3038 ret = of_property_read_u16_array(node, propname, regs, nb);
3039 if (ret) {
3040 dev_warn(chip->dev, "failed to read %s: %d\n", propname, ret);
3041 goto shadow_out;
3042 }
3043
3044 for (i = 0; i < nb; i += 2) {
3045 const int idx = max17x0x_cache_index_of(nRAM, regs[i]);
3046 nRAM->cache_data[idx] = regs[i + 1];
3047 }
3048
3049shadow_out:
3050 kfree(regs);
3051 return ret;
3052}
3053
3054/* support for initial batch of ill configured max1720x packs */
3055static void max1720x_consistency_check(struct max17x0x_cache_data *cache)
3056{
3057 int nvcfg_idx = max17x0x_cache_index_of(cache, MAX1720X_NNVCFG0);
3058 int ncgain_idx = max17x0x_cache_index_of(cache, MAX1720X_NCGAIN);
3059 u16 *nRAM_updated = cache->cache_data;
3060
3061 if ((nRAM_updated[nvcfg_idx] & MAX1720X_NNVCFG0_ENCG) &&
3062 ((nRAM_updated[ncgain_idx] == 0) ||
3063 (nRAM_updated[ncgain_idx] == 0x0400)))
3064 nRAM_updated[ncgain_idx] = 0x4000;
3065}
3066
3067static int max17x0x_read_dt_version(struct device_node *node,
3068 int gauge_type, u8 *reg, u8 *val)
3069{
3070 int ret;
3071 const char *propname;
3072 u8 version[2];
3073
3074 if (gauge_type == MAX1730X_GAUGE_TYPE) {
3075 propname = "maxim,n_regval_1730x_ver";
3076 } else if (gauge_type == MAX1720X_GAUGE_TYPE) {
3077 propname = "maxim,n_regval_1720x_ver";
3078 } else {
3079 return -ENOTSUPP;
3080 }
3081
3082 ret = of_property_read_u8_array(node, propname,
3083 version,
3084 sizeof(version));
3085 if (ret < 0)
3086 return -ENODATA;
3087
3088 *reg = version[0];
3089 *val = version[1];
3090
3091 return 0;
3092}
3093
3094static int max17x0x_read_dt_version_por(struct device_node *node,
3095 int gauge_type, u8 *reg, u8 *val)
3096{
3097 int ret;
3098 const char *propname;
3099 u8 version[2];
3100
3101 if (gauge_type == MAX1730X_GAUGE_TYPE) {
3102 propname = "maxim,n_regval_1730x_ver_por";
3103 } else if (gauge_type == MAX1720X_GAUGE_TYPE) {
3104 propname = "maxim,n_regval_1720x_ver_por";
3105 } else {
3106 return -ENOTSUPP;
3107 }
3108
3109 ret = of_property_read_u8_array(node, propname,
3110 version,
3111 sizeof(version));
3112 if (ret < 0)
3113 return -ENODATA;
3114
3115 *reg = version[0];
3116 *val = version[1];
3117
3118 return 0;
3119}
3120
3121static int max17x0x_handle_dt_shadow_config(struct max1720x_chip *chip)
3122{
3123 int ret, rc, glob_cnt;
3124 const char *propname = NULL;
3125 struct max17x0x_cache_data nRAM_c;
3126 struct max17x0x_cache_data nRAM_u;
3127 int ver_idx = -1;
3128 u8 vreg, vval;
3129
3130 /* for devices that don't support max1720x_fg_reset() */
3131 if (!chip->shadow_override || chip->gauge_type == -1)
3132 return 0;
3133
3134 if (chip->gauge_type == MAX1730X_GAUGE_TYPE)
3135 propname = "maxim,n_regval_1730x";
3136 else
3137 propname = "maxim,n_regval_1720x";
3138
3139 ret = max17x0x_nvram_cache_init(&nRAM_c, chip->gauge_type);
3140 if (ret < 0)
3141 return ret;
3142
3143 ret = max17x0x_cache_load(&nRAM_c, &chip->regmap_nvram);
3144 if (ret < 0) {
3145 dev_err(chip->dev, "Failed to read config from shadow RAM\n");
3146 goto error_out;
3147 }
3148
3149 ret = max17x0x_cache_dup(&nRAM_u, &nRAM_c);
3150 if (ret < 0)
3151 goto error_out;
3152
3153 /* apply overrides */
3154 if (chip->batt_node) {
3155 int batt_cnt;
3156
3157 batt_cnt = of_property_count_elems_of_size(chip->batt_node,
3158 propname,
3159 sizeof(u16));
3160 max17x0x_apply_regval_shadow(chip, chip->batt_node,
3161 &nRAM_u,
3162 batt_cnt);
3163 }
3164
3165 glob_cnt = of_property_count_elems_of_size(chip->dev->of_node,
3166 propname,
3167 sizeof(u16));
3168 max17x0x_apply_regval_shadow(chip, chip->dev->of_node,
3169 &nRAM_u,
3170 glob_cnt);
3171
3172 if (chip->gauge_type == MAX1720X_GAUGE_TYPE)
3173 max1720x_consistency_check(&nRAM_u);
3174
3175 rc = max17x0x_read_dt_version(chip->dev->of_node,
3176 chip->gauge_type, &vreg, &vval);
3177 if (rc == 0) {
3178 /*
3179 * Versioning enforced: reset the gauge (and overwrite
3180 * version) only if the version in device tree is
3181 * greater than the version in the gauge.
3182 */
3183 ver_idx = max17x0x_cache_index_of(&nRAM_u, vreg);
3184 if (ver_idx < 0) {
3185 dev_err(chip->dev, "version register %x is not mapped\n",
3186 vreg);
3187 } else if ((nRAM_u.cache_data[ver_idx] & 0xff) < vval) {
3188 /*
3189 * force version in dt, will write (and reset fg)
3190 * only when less than the version in nRAM_c
3191 */
3192 dev_info(chip->dev,
3193 "DT version updated %d -> %d\n",
3194 nRAM_u.cache_data[ver_idx] & 0xff,
3195 vval);
3196
3197 nRAM_u.cache_data[ver_idx] &= 0xff00;
3198 nRAM_u.cache_data[ver_idx] |= vval;
3199 chip->needs_reset = true;
3200 }
3201 }
3202
3203 if (max17x0x_cache_memcmp(&nRAM_c, &nRAM_u)) {
3204 bool fg_reset = false;
3205
3206 if (ver_idx < 0) {
3207 /*
3208 * Versioning not enforced: nConvgCfg take effect
3209 * without resetting the gauge
3210 */
3211 const int idx = max17x0x_cache_index_of(&nRAM_u,
3212 MAX1720X_NCONVGCFG);
3213 nRAM_c.cache_data[idx] = nRAM_u.cache_data[idx];
3214 fg_reset = max17x0x_cache_memcmp(&nRAM_u, &nRAM_c) != 0;
3215 }
3216
3217 ret = max17x0x_cache_store(&nRAM_u, &chip->regmap_nvram);
3218 if (ret < 0) {
3219 dev_err(chip->dev,
3220 "Failed to write config from shadow RAM\n");
3221 goto error_out;
3222 }
3223
3224 /* different reason for reset */
3225 if (fg_reset) {
3226 chip->needs_reset = true;
3227 dev_info(chip->dev,
3228 "DT config differs from shadow, resetting\n");
3229 }
3230 }
3231
3232error_out:
3233 max17x0x_cache_free(&nRAM_c);
3234 max17x0x_cache_free(&nRAM_u);
3235
3236 return ret;
3237}
3238
3239static int max17x0x_apply_regval_register(struct max1720x_chip *chip,
3240 struct device_node *node)
3241{
3242 int cnt, ret = 0, idx, err;
3243 u16 *regs, data;
3244 const char *propname;
3245
3246 propname = (chip->gauge_type == MAX1730X_GAUGE_TYPE) ?
3247 "maxim,r_regval_1730x" : "maxim,r_regval_1720x";
3248
3249 cnt = of_property_count_elems_of_size(node, propname, sizeof(u16));
3250 if (!node || cnt <= 0)
3251 return 0;
3252
3253 if (cnt & 1) {
3254 dev_warn(chip->dev, "%s %s u16 elems count is not even: %d\n",
3255 node->name, propname, cnt);
3256 return -EINVAL;
3257 }
3258
3259 regs = batt_alloc_array(cnt, sizeof(u16));
3260 if (!regs)
3261 return -ENOMEM;
3262
3263 ret = of_property_read_u16_array(node, propname, regs, cnt);
3264 if (ret) {
3265 dev_warn(chip->dev, "failed to read %s %s: %d\n",
3266 node->name, propname, ret);
3267 goto register_out;
3268 }
3269
3270 for (idx = 0; idx < cnt; idx += 2) {
3271 if (max1720x_is_reg(chip->dev, regs[idx])) {
3272 err = REGMAP_READ(&chip->regmap, regs[idx], &data);
3273 if (!err && data != regs[idx + 1])
3274 REGMAP_WRITE(&chip->regmap, regs[idx],
3275 regs[idx + 1]);
3276 }
3277 }
3278register_out:
3279 kfree(regs);
3280 return ret;
3281}
3282
3283static int max17x0x_handle_dt_register_config(struct max1720x_chip *chip)
3284{
3285 int ret = 0;
3286
3287 if (chip->batt_node)
3288 ret = max17x0x_apply_regval_register(chip, chip->batt_node);
3289
3290 if (ret)
3291 return ret;
3292
3293 ret = max17x0x_apply_regval_register(chip, chip->dev->of_node);
3294
3295 return ret;
3296}
3297
3298static int max1720x_handle_dt_nconvgcfg(struct max1720x_chip *chip)
3299{
3300 int ret = 0, i;
3301 struct device_node *node = chip->dev->of_node;
3302
3303 chip->curr_convgcfg_idx = -1;
3304 mutex_init(&chip->convgcfg_lock);
3305
3306 ret = of_property_read_u32(node, "google,cap-tsettle",
3307 (u32 *)&chip->cap_estimate.cap_tsettle);
3308 if (ret < 0)
3309 chip->cap_estimate.cap_tsettle = DEFAULT_CAP_SETTLE_INTERVAL;
3310 chip->cap_estimate.cap_tsettle =
3311 chip->cap_estimate.cap_tsettle * 60 * 1000;
3312
3313 ret = of_property_read_u32(node, "google,cap-filt-length",
3314 (u32 *)&chip->cap_estimate.cap_filt_length);
3315 if (ret < 0)
3316 chip->cap_estimate.cap_filt_length = DEFAULT_CAP_FILTER_LENGTH;
3317
3318 chip->nb_convgcfg =
3319 of_property_count_elems_of_size(node, "maxim,nconvgcfg-temp-limits",
3320 sizeof(s16));
3321 if (!chip->nb_convgcfg)
3322 return 0;
3323
3324 ret = of_property_read_s32(node, "maxim,nconvgcfg-temp-hysteresis",
3325 &chip->convgcfg_hysteresis);
3326 if (ret < 0)
3327 chip->convgcfg_hysteresis = 10;
3328 else if (chip->convgcfg_hysteresis < 0)
3329 chip->convgcfg_hysteresis = 10;
3330 if (ret == 0)
3331 dev_info(chip->dev, "%s maxim,nconvgcfg-temp-hysteresis = %d\n",
3332 node->name, chip->convgcfg_hysteresis);
3333
3334 if (chip->nb_convgcfg != of_property_count_elems_of_size(node,
3335 "maxim,nconvgcfg-values",
3336 sizeof(u16))) {
3337 dev_warn(chip->dev, "%s maxim,nconvgcfg-values and maxim,nconvgcfg-temp-limits are missmatching number of elements\n",
3338 node->name);
3339 return -EINVAL;
3340 }
3341 chip->temp_convgcfg = (s16 *)devm_kmalloc_array(chip->dev,
3342 chip->nb_convgcfg,
3343 sizeof(s16),
3344 GFP_KERNEL);
3345 if (!chip->temp_convgcfg)
3346 return -ENOMEM;
3347
3348 chip->convgcfg_values = (u16 *)devm_kmalloc_array(chip->dev,
3349 chip->nb_convgcfg,
3350 sizeof(u16),
3351 GFP_KERNEL);
3352 if (!chip->convgcfg_values) {
3353 devm_kfree(chip->dev, chip->temp_convgcfg);
3354 chip->temp_convgcfg = NULL;
3355 return -ENOMEM;
3356 }
3357
3358 ret = of_property_read_u16_array(node, "maxim,nconvgcfg-temp-limits",
3359 (u16 *) chip->temp_convgcfg,
3360 chip->nb_convgcfg);
3361 if (ret) {
3362 dev_warn(chip->dev, "failed to read maxim,nconvgcfg-temp-limits: %d\n",
3363 ret);
3364 goto error;
3365 }
3366
3367 ret = of_property_read_u16_array(node, "maxim,nconvgcfg-values",
3368 chip->convgcfg_values,
3369 chip->nb_convgcfg);
3370 if (ret) {
3371 dev_warn(chip->dev, "failed to read maxim,nconvgcfg-values: %d\n",
3372 ret);
3373 goto error;
3374 }
3375 for (i = 1; i < chip->nb_convgcfg; i++) {
3376 if (chip->temp_convgcfg[i] < chip->temp_convgcfg[i-1]) {
3377 dev_warn(chip->dev, "nconvgcfg-temp-limits idx:%d < idx:%d\n",
3378 i, i-1);
3379 goto error;
3380 }
3381 if ((chip->temp_convgcfg[i] - chip->temp_convgcfg[i-1])
3382 <= chip->convgcfg_hysteresis) {
3383 dev_warn(chip->dev, "nconvgcfg-temp-hysteresis smaller than idx:%d, idx:%d\n",
3384 i, i-1);
3385 goto error;
3386 }
3387 }
3388
3389 chip->nb_empty_voltage = of_property_count_elems_of_size(node,
3390 "maxim,empty-voltage",
3391 sizeof(u16));
3392 if (chip->nb_empty_voltage > 0 &&
3393 chip->nb_empty_voltage % NB_CYCLE_BUCKETS == 0) {
3394 chip->empty_voltage = (u16 *)devm_kmalloc_array(chip->dev,
3395 chip->nb_empty_voltage,
3396 sizeof(u16),
3397 GFP_KERNEL);
3398 if (!chip->empty_voltage)
3399 goto error;
3400
3401 ret = of_property_read_u16_array(node, "maxim,empty-voltage",
3402 chip->empty_voltage,
3403 chip->nb_empty_voltage);
3404 if (ret) {
3405 dev_warn(chip->dev,
3406 "failed to read maxim,empty-voltage: %d\n",
3407 ret);
3408 }
3409 } else
3410 dev_warn(chip->dev,
3411 "maxim,empty-voltage is missmatching the number of elements, nb = %d\n",
3412 chip->nb_empty_voltage);
3413error:
3414 if (ret) {
3415 devm_kfree(chip->dev, chip->temp_convgcfg);
3416 devm_kfree(chip->dev, chip->convgcfg_values);
3417 chip->temp_convgcfg = NULL;
3418 }
3419
3420 return ret;
3421}
3422
Jenny Ho80a583b2021-11-15 01:46:25 +08003423static int max1720x_handle_dt_filtercfg(struct max1720x_chip *chip)
3424{
3425 struct device_node *node = chip->dev->of_node;
3426 struct max1720x_dyn_filtercfg *filtercfg = &chip->dyn_filtercfg;
3427 int ret = 0;
3428
3429 mutex_init(&filtercfg->lock);
3430
3431 ret = of_property_read_s32(node, "maxim,filtercfg-temp",
3432 &filtercfg->temp);
3433 if (ret)
3434 goto not_enable;
3435
3436 ret = of_property_read_s32(node, "maxim,filtercfg-temp-hysteresis",
3437 &filtercfg->hysteresis);
3438 if (ret)
3439 filtercfg->hysteresis = FILTERCFG_TEMP_HYSTERESIS;
3440
3441 ret = of_property_read_u16(node, "maxim,filtercfg-default",
3442 &filtercfg->default_val);
3443 if (ret)
3444 goto not_enable;
3445
3446 ret = of_property_read_u16(node, "maxim,filtercfg-adjust",
3447 &filtercfg->adjust_val);
3448 if (ret)
3449 goto not_enable;
3450
3451 dev_info(chip->dev, "%s filtercfg: temp:%d(hys:%d), default:%#X adjust:%#X\n",
3452 node->name, filtercfg->temp, filtercfg->hysteresis,
3453 filtercfg->default_val, filtercfg->adjust_val);
3454
3455 return ret;
3456
3457not_enable:
3458 filtercfg->temp = -1;
3459 return ret;
3460}
3461
Ken Tsou8acade12020-07-09 03:17:35 +08003462static int get_irq_none_cnt(void *data, u64 *val)
3463{
3464 struct max1720x_chip *chip = (struct max1720x_chip *)data;
3465
3466 *val = chip->debug_irq_none_cnt;
3467 return 0;
3468}
3469
3470static int set_irq_none_cnt(void *data, u64 val)
3471{
3472 struct max1720x_chip *chip = (struct max1720x_chip *)data;
3473
3474 if (val == 0)
3475 chip->debug_irq_none_cnt = 0;
3476 return 0;
3477}
3478
3479DEFINE_SIMPLE_ATTRIBUTE(irq_none_cnt_fops, get_irq_none_cnt,
3480 set_irq_none_cnt, "%llu\n");
3481
3482
3483static int debug_fg_reset(void *data, u64 val)
3484{
3485 struct max1720x_chip *chip = data;
3486 int ret;
3487
3488 if (val == 0)
3489 ret = max17x0x_fg_reset(chip);
3490 else if (val == 1)
3491 ret = max1720x_full_reset(chip);
3492 else
3493 ret = -EINVAL;
3494
3495 return ret;
3496}
3497
3498DEFINE_SIMPLE_ATTRIBUTE(debug_fg_reset_fops, NULL, debug_fg_reset, "%llu\n");
3499
3500static int debug_ce_start(void *data, u64 val)
3501{
3502 struct max1720x_chip *chip = (struct max1720x_chip *)data;
3503
3504 batt_ce_start(&chip->cap_estimate, val);
3505 return 0;
3506}
3507
3508DEFINE_SIMPLE_ATTRIBUTE(debug_ce_start_fops, NULL, debug_ce_start, "%llu\n");
3509
3510/* Model reload will be disabled if the node is not found */
3511static int max1720x_init_model(struct max1720x_chip *chip)
3512{
3513 void *model_data;
3514
Jenny Hod52e05d2021-04-12 17:16:20 +08003515 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
3516 return 0;
3517
Ken Tsou8acade12020-07-09 03:17:35 +08003518 /* ->batt_id negative for no lookup */
3519 if (chip->batt_id >= 0) {
AleX Pelosifed7fb12020-11-10 01:22:22 -08003520 chip->batt_node = max1720x_find_batt_node(chip);
AleX Pelosi962aedf2021-01-07 15:39:43 -08003521 pr_debug("node found=%d for ID=%d algo=%d\n",
3522 !!chip->batt_node, chip->batt_id,
3523 chip->drift_data.algo_ver);
Ken Tsou8acade12020-07-09 03:17:35 +08003524 }
3525
3526 /* TODO: split allocation and initialization */
3527 model_data = max_m5_init_data(chip->dev, chip->batt_node ?
3528 chip->batt_node : chip->dev->of_node,
3529 &chip->regmap);
3530 if (IS_ERR(model_data))
3531 return PTR_ERR(model_data);
3532
3533 chip->model_data = model_data;
AleX Pelosi962aedf2021-01-07 15:39:43 -08003534
Ken Tsou8acade12020-07-09 03:17:35 +08003535 if (!chip->batt_node) {
AleX Pelosi962aedf2021-01-07 15:39:43 -08003536 dev_warn(chip->dev, "No child node for ID=%d, algo=%d\n",
3537 chip->batt_id, chip->drift_data.algo_ver);
Ken Tsou8acade12020-07-09 03:17:35 +08003538 chip->model_reload = MAX_M5_LOAD_MODEL_DISABLED;
3539 } else {
AleX Pelosi962aedf2021-01-07 15:39:43 -08003540 u32 data32;
3541 int rc;
3542
3543 /* align algo_ver for capacity drift to model */
3544 rc = of_property_read_u32(chip->batt_node, "maxim,algo-version",
3545 &data32);
3546 if (rc == 0)
3547 chip->drift_data.algo_ver = data32;
3548
3549 pr_debug("model_data ok for ID=%d, algo=%d\n",
3550 chip->batt_id, chip->drift_data.algo_ver);
Ken Tsou8acade12020-07-09 03:17:35 +08003551 chip->model_reload = MAX_M5_LOAD_MODEL_IDLE;
3552 }
3553
3554 return 0;
3555}
3556
3557/* change battery_id and cause reload of the FG model */
3558static int debug_batt_id_set(void *data, u64 val)
3559{
3560 struct max1720x_chip *chip = (struct max1720x_chip *)data;
3561 int ret;
3562
3563 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
3564 return -EINVAL;
3565
3566 mutex_lock(&chip->model_lock);
3567
3568 /* reset state (if needed) */
3569 if (chip->model_data)
3570 max_m5_free_data(chip->model_data);
3571 chip->batt_id = val;
3572
3573 /* re-init the model data (lookup in DT) */
3574 ret = max1720x_init_model(chip);
3575 if (ret == 0)
3576 max1720x_model_reload(chip, true);
3577
3578 mutex_unlock(&chip->model_lock);
3579
AleX Pelosi5077fc52020-09-10 21:44:48 -07003580 dev_info(chip->dev, "Force model for batt_id=%llu (%d)\n", val, ret);
Ken Tsou8acade12020-07-09 03:17:35 +08003581 return 0;
3582}
3583
AleX Pelosi5077fc52020-09-10 21:44:48 -07003584DEFINE_SIMPLE_ATTRIBUTE(debug_batt_id_fops, NULL, debug_batt_id_set, "%llu\n");
Ken Tsou8acade12020-07-09 03:17:35 +08003585
Ken Tsou8acade12020-07-09 03:17:35 +08003586/*
3587 * dump with "cat /d/max1720x/nvram_por | xxd"
3588 * NOTE: for testing add a setter that initialize chip->nRAM_por (if not
3589 * initialized) and use _load() to read NVRAM.
3590 */
3591static ssize_t debug_get_nvram_por(struct file *filp,
3592 char __user *buf,
3593 size_t count, loff_t *ppos)
3594{
3595 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
3596 int size;
3597
3598 if (!chip || !chip->nRAM_por.cache_data)
3599 return -ENODATA;
3600
3601 size = chip->nRAM_por.atom.size > count ?
3602 count : chip->nRAM_por.atom.size;
3603
3604 return simple_read_from_buffer(buf, count, ppos,
3605 chip->nRAM_por.cache_data,
3606 size);
3607}
3608
3609BATTERY_DEBUG_ATTRIBUTE(debug_nvram_por_fops, debug_get_nvram_por, NULL);
3610
AleX Pelosi8c5fa772020-10-03 13:36:56 -07003611static int debug_fake_battery_set(void *data, u64 val)
3612{
3613 struct max1720x_chip *chip = (struct max1720x_chip *)data;
3614
3615 chip->fake_battery = (int)val;
3616 return 0;
3617}
3618
3619DEFINE_SIMPLE_ATTRIBUTE(debug_fake_battery_fops, NULL,
3620 debug_fake_battery_set, "%llu\n");
3621
Ken Tsou8acade12020-07-09 03:17:35 +08003622static void max17x0x_reglog_dump(struct max17x0x_reglog *regs,
3623 size_t size,
3624 char *buff)
3625{
3626 int i, len = 0;
3627
3628 for (i = 0; i < NB_REGMAP_MAX; i++) {
3629 if (size <= len)
3630 break;
3631 if (test_bit(i, regs->valid))
3632 len += scnprintf(&buff[len], size - len, "%02X:%04X\n",
3633 i, regs->data[i]);
3634 }
3635
3636 if (len == 0)
3637 scnprintf(buff, size, "No record\n");
3638}
3639
3640static ssize_t debug_get_reglog_writes(struct file *filp,
3641 char __user *buf,
3642 size_t count, loff_t *ppos)
3643{
3644 char *buff;
3645 ssize_t rc = 0;
3646 struct max17x0x_reglog *reglog =
3647 (struct max17x0x_reglog *)filp->private_data;
3648
3649 buff = kmalloc(count, GFP_KERNEL);
3650 if (!buff)
3651 return -ENOMEM;
3652
3653 max17x0x_reglog_dump(reglog, count, buff);
3654 rc = simple_read_from_buffer(buf, count, ppos, buff, strlen(buff));
3655
3656 kfree(buff);
3657
3658 return rc;
3659}
3660
3661BATTERY_DEBUG_ATTRIBUTE(debug_reglog_writes_fops,
3662 debug_get_reglog_writes, NULL);
3663
3664static ssize_t max1720x_show_custom_model(struct file *filp, char __user *buf,
Thierry Strudel4ab0fcb2021-02-02 10:31:46 -08003665 size_t count, loff_t *ppos)
Ken Tsou8acade12020-07-09 03:17:35 +08003666{
3667 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
3668 char *tmp;
3669 int len;
3670
3671 if (!chip->model_data)
3672 return -EINVAL;
3673
3674 tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
3675 if (!tmp)
3676 return -ENOMEM;
3677
3678 mutex_lock(&chip->model_lock);
3679 len = max_m5_fg_model_cstr(tmp, PAGE_SIZE, chip->model_data);
3680 mutex_unlock(&chip->model_lock);
3681
3682 if (len > 0)
3683 len = simple_read_from_buffer(buf, count, ppos, tmp, len);
3684
3685 kfree(tmp);
3686
3687 return len;
3688}
3689
3690static ssize_t max1720x_set_custom_model(struct file *filp,
3691 const char __user *user_buf,
3692 size_t count, loff_t *ppos)
3693{
3694 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
3695 char *tmp;
3696 int ret;
3697
3698 if (!chip->model_data)
3699 return -EINVAL;
3700
3701 tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
3702 if (!tmp)
3703 return -ENOMEM;
3704
3705 ret = simple_write_to_buffer(tmp, PAGE_SIZE, ppos, user_buf, count);
juyuchen8843d9e2021-01-14 18:05:09 +08003706 if (!ret) {
3707 kfree(tmp);
Ken Tsou8acade12020-07-09 03:17:35 +08003708 return -EFAULT;
juyuchen8843d9e2021-01-14 18:05:09 +08003709 }
Ken Tsou8acade12020-07-09 03:17:35 +08003710
3711 mutex_lock(&chip->model_lock);
3712 ret = max_m5_fg_model_sscan(chip->model_data, tmp, count);
3713 if (ret < 0)
3714 count = ret;
3715 mutex_unlock(&chip->model_lock);
3716
3717 kfree(tmp);
3718
3719 return count;
3720}
3721
3722BATTERY_DEBUG_ATTRIBUTE(debug_m5_custom_model_fops, max1720x_show_custom_model,
3723 max1720x_set_custom_model);
3724
AleX Pelosifc6f66d2021-01-12 18:14:48 -08003725
3726static int debug_sync_model(void *data, u64 val)
3727{
3728 struct max1720x_chip *chip = data;
3729 int ret;
3730
3731 if (!chip->model_data)
3732 return -EINVAL;
3733
3734 /* re-read new state from Fuel gauge, save to storage */
3735 ret = max_m5_model_read_state(chip->model_data);
AleX Pelosi00eec962021-01-13 19:32:33 -08003736 if (ret == 0) {
3737 ret = max_m5_model_check_state(chip->model_data);
3738 if (ret < 0)
3739 pr_warn("%s: warning invalid state %d\n", __func__, ret);
3740
AleX Pelosifc6f66d2021-01-12 18:14:48 -08003741 ret = max_m5_save_state_data(chip->model_data);
AleX Pelosi00eec962021-01-13 19:32:33 -08003742 }
AleX Pelosifc6f66d2021-01-12 18:14:48 -08003743
3744 return ret;
3745}
3746
3747DEFINE_SIMPLE_ATTRIBUTE(debug_sync_model_fops, NULL, debug_sync_model, "%llu\n");
3748
3749
AleX Pelosi45558f82021-01-12 00:34:09 -08003750static ssize_t max1720x_show_debug_data(struct file *filp, char __user *buf,
Thierry Strudel4ab0fcb2021-02-02 10:31:46 -08003751 size_t count, loff_t *ppos)
AleX Pelosi45558f82021-01-12 00:34:09 -08003752{
3753 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
3754 char msg[8];
3755 u16 data;
3756 int ret;
3757
3758 ret = REGMAP_READ(&chip->regmap, chip->debug_reg_address, &data);
3759 if (ret < 0)
3760 return ret;
3761
3762 ret = scnprintf(msg, sizeof(msg), "%x\n", data);
3763
3764 return simple_read_from_buffer(buf, count, ppos, msg, ret);
3765}
3766
3767static ssize_t max1720x_set_debug_data(struct file *filp,
3768 const char __user *user_buf,
3769 size_t count, loff_t *ppos)
3770{
3771 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
3772 char temp[8] = { };
3773 u16 data;
3774 int ret;
3775
3776 ret = simple_write_to_buffer(temp, sizeof(temp) - 1, ppos, user_buf, count);
3777 if (!ret)
3778 return -EFAULT;
3779
3780 ret = kstrtou16(temp, 16, &data);
3781 if (ret < 0)
3782 return ret;
3783
3784 ret = REGMAP_WRITE(&chip->regmap, chip->debug_reg_address, data);
3785 if (ret < 0)
3786 return ret;
3787
3788 return count;
3789}
3790
3791BATTERY_DEBUG_ATTRIBUTE(debug_reg_data_fops, max1720x_show_debug_data,
3792 max1720x_set_debug_data);
3793
Jenny Hof98812c2021-06-11 16:35:53 +08003794static ssize_t max1720x_show_reg_all(struct file *filp, char __user *buf,
3795 size_t count, loff_t *ppos)
3796{
3797 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
Jenny Ho3cfbc9b2021-10-25 10:23:20 +08003798 const struct max17x0x_regmap *map = &chip->regmap;
Jenny Hof98812c2021-06-11 16:35:53 +08003799 u32 reg_address;
Jenny Ho3cfbc9b2021-10-25 10:23:20 +08003800 unsigned int data;
Jenny Hof98812c2021-06-11 16:35:53 +08003801 char *tmp;
3802 int ret = 0, len = 0;
3803
Jenny Ho3cfbc9b2021-10-25 10:23:20 +08003804 if (!map->regmap) {
3805 pr_err("Failed to read, no regmap\n");
3806 return -EIO;
3807 }
3808
Jenny Hof98812c2021-06-11 16:35:53 +08003809 tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
3810 if (!tmp)
3811 return -ENOMEM;
3812
3813 for (reg_address = 0; reg_address <= 0xFF; reg_address++) {
Jenny Ho3cfbc9b2021-10-25 10:23:20 +08003814 ret = regmap_read(map->regmap, reg_address, &data);
Jenny Hof98812c2021-06-11 16:35:53 +08003815 if (ret < 0)
3816 continue;
3817
3818 len += scnprintf(tmp + len, PAGE_SIZE - len, "%02x: %04x\n", reg_address, data);
3819 }
3820
3821 if (len > 0)
3822 len = simple_read_from_buffer(buf, count, ppos, tmp, strlen(tmp));
3823
3824 kfree(tmp);
3825
3826 return len;
3827}
3828
3829BATTERY_DEBUG_ATTRIBUTE(debug_reg_all_fops, max1720x_show_reg_all, NULL);
3830
Jenny Ho03a73aa2022-06-19 01:17:32 +00003831static ssize_t max1720x_show_nvreg_all(struct file *filp, char __user *buf,
3832 size_t count, loff_t *ppos)
3833{
3834 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
3835 const struct max17x0x_regmap *map = &chip->regmap_nvram;
3836 u32 reg_address;
3837 unsigned int data;
3838 char *tmp;
3839 int ret = 0, len = 0;
3840
3841 if (!map->regmap) {
3842 pr_err("Failed to read, no regmap\n");
3843 return -EIO;
3844 }
3845
3846 tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
3847 if (!tmp)
3848 return -ENOMEM;
3849
3850 for (reg_address = 0; reg_address <= 0xFF; reg_address++) {
3851 ret = regmap_read(map->regmap, reg_address, &data);
3852 if (ret < 0)
3853 continue;
3854
3855 len += scnprintf(tmp + len, PAGE_SIZE - len, "%02x: %04x\n", reg_address, data);
3856 }
3857
3858 if (len > 0)
3859 len = simple_read_from_buffer(buf, count, ppos, tmp, strlen(tmp));
3860
3861 kfree(tmp);
3862
3863 return len;
3864}
3865
3866BATTERY_DEBUG_ATTRIBUTE(debug_nvreg_all_fops, max1720x_show_nvreg_all, NULL);
3867
AleX Pelosib499a5c2021-12-06 11:28:09 -08003868static ssize_t max1720x_force_psy_update(struct file *filp,
3869 const char __user *user_buf,
3870 size_t count, loff_t *ppos)
3871{
3872 struct max1720x_chip *chip = (struct max1720x_chip *)filp->private_data;
3873
3874 if (chip->psy)
3875 power_supply_changed(chip->psy);
3876
3877 return count;
3878}
3879
3880BATTERY_DEBUG_ATTRIBUTE(debug_force_psy_update_fops, NULL,
3881 max1720x_force_psy_update);
Jenny Ho76e43d92022-04-29 06:05:30 +08003882
3883static int debug_cnhs_reset(void *data, u64 val)
3884{
Jenny Hoa1e85e92022-05-16 13:36:05 +08003885 struct max1720x_chip *chip = data;
Jenny Ho76e43d92022-04-29 06:05:30 +08003886 u16 reset_val;
3887 int ret;
3888
3889 reset_val = (u16)val;
3890
3891 ret = gbms_storage_write(GBMS_TAG_CNHS, &reset_val,
3892 sizeof(reset_val));
Jenny Hoa1e85e92022-05-16 13:36:05 +08003893 dev_info(chip->dev, "reset CNHS to %d, (ret=%d)\n", reset_val, ret);
Jenny Ho76e43d92022-04-29 06:05:30 +08003894
3895 return ret;
3896}
3897
3898DEFINE_SIMPLE_ATTRIBUTE(debug_reset_cnhs_fops, NULL, debug_cnhs_reset, "%llu\n");
3899
3900static int debug_gmsr_reset(void *data, u64 val)
3901{
3902 struct max1720x_chip *chip = data;
3903 int ret;
3904
3905 ret = max_m5_reset_state_data(chip->model_data);
Jenny Hoa1e85e92022-05-16 13:36:05 +08003906 dev_info(chip->dev, "reset GMSR (ret=%d)\n", ret);
Jenny Ho76e43d92022-04-29 06:05:30 +08003907
3908 return ret;
3909}
3910
3911DEFINE_SIMPLE_ATTRIBUTE(debug_reset_gmsr_fops, NULL, debug_gmsr_reset, "%llu\n");
3912
AleX Pelosi4608f2d2020-08-27 10:02:50 -07003913/*
3914 * TODO: add the building blocks of google capacity
3915 *
3916 * case POWER_SUPPLY_PROP_DELTA_CC_SUM:
3917 * val->intval = chip->cap_estimate.delta_cc_sum;
3918 * break;
3919 * case POWER_SUPPLY_PROP_DELTA_VFSOC_SUM:
Thierry Strudel4ab0fcb2021-02-02 10:31:46 -08003920 * val->intval = chip->cap_estimate.delta_vfsoc_sum;
AleX Pelosi4608f2d2020-08-27 10:02:50 -07003921 * break;
3922 */
3923
AleX Pelosi43986542022-05-03 15:33:18 -07003924static ssize_t act_impedance_store(struct device *dev,
3925 struct device_attribute *attr,
3926 const char *buf, size_t count) {
3927 struct power_supply *psy = container_of(dev, struct power_supply, dev);
3928 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
AleX Pelosi43986542022-05-03 15:33:18 -07003929 int value, ret = 0;
3930
3931 ret = kstrtoint(buf, 0, &value);
3932 if (ret < 0)
3933 return ret;
3934
3935 mutex_lock(&chip->model_lock);
3936
AleX Pelosic1cd4752022-05-04 02:15:02 -07003937 ret = max1720x_health_update_ai(chip, value);
AleX Pelosi43986542022-05-03 15:33:18 -07003938 if (ret == 0)
3939 chip->bhi_acim = 0;
3940
Jenny Hoa1e85e92022-05-16 13:36:05 +08003941 dev_info(chip->dev, "value=%d (%d)\n", value, ret);
AleX Pelosi43986542022-05-03 15:33:18 -07003942
3943 mutex_unlock(&chip->model_lock);
3944 return count;
3945}
3946
3947static ssize_t act_impedance_show(struct device *dev,
3948 struct device_attribute *attr, char *buf)
3949{
3950 struct power_supply *psy = container_of(dev, struct power_supply, dev);
3951 struct max1720x_chip *chip = power_supply_get_drvdata(psy);
3952
3953 return scnprintf(buf, PAGE_SIZE, "%d\n", max1720x_health_get_ai(chip));
3954}
3955
3956static const DEVICE_ATTR_RW(act_impedance);
3957
3958static int max17x0x_init_sysfs(struct max1720x_chip *chip)
Ken Tsou8acade12020-07-09 03:17:35 +08003959{
3960 struct dentry *de;
AleX Pelosi43986542022-05-03 15:33:18 -07003961 int ret;
3962
3963 /* stats */
3964 ret = device_create_file(&chip->psy->dev, &dev_attr_act_impedance);
3965 if (ret)
3966 dev_err(&chip->psy->dev, "Failed to create act_impedance\n");
Ken Tsou8acade12020-07-09 03:17:35 +08003967
Jenny Ho36b6c9f2020-12-21 09:57:16 +08003968 de = debugfs_create_dir(chip->max1720x_psy_desc.name, 0);
Ken Tsou8acade12020-07-09 03:17:35 +08003969 if (IS_ERR_OR_NULL(de))
3970 return -ENOENT;
3971
AleX Pelosifed7fb12020-11-10 01:22:22 -08003972 debugfs_create_file("irq_none_cnt", 0644, de, chip, &irq_none_cnt_fops);
3973 debugfs_create_file("nvram_por", 0440, de, chip, &debug_nvram_por_fops);
3974 debugfs_create_file("fg_reset", 0400, de, chip, &debug_fg_reset_fops);
3975 debugfs_create_file("ce_start", 0400, de, chip, &debug_ce_start_fops);
AleX Pelosib499a5c2021-12-06 11:28:09 -08003976 debugfs_create_file("fake_battery", 0400, de, chip, &debug_fake_battery_fops);
AleX Pelosifed7fb12020-11-10 01:22:22 -08003977 debugfs_create_file("batt_id", 0600, de, chip, &debug_batt_id_fops);
AleX Pelosib499a5c2021-12-06 11:28:09 -08003978 debugfs_create_file("force_psy_update", 0600, de, chip, &debug_force_psy_update_fops);
Ken Tsou8acade12020-07-09 03:17:35 +08003979
3980 if (chip->regmap.reglog)
3981 debugfs_create_file("regmap_writes", 0440, de,
3982 chip->regmap.reglog,
3983 &debug_reglog_writes_fops);
3984
3985 if (chip->regmap_nvram.reglog)
3986 debugfs_create_file("regmap_nvram_writes", 0440, de,
3987 chip->regmap_nvram.reglog,
3988 &debug_reglog_writes_fops);
3989
AleX Pelosi70444902020-09-08 15:46:12 -07003990 if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
Jenny Hof98812c2021-06-11 16:35:53 +08003991 debugfs_create_file("fg_model", 0444, de, chip,
Ken Tsou8acade12020-07-09 03:17:35 +08003992 &debug_m5_custom_model_fops);
AleX Pelosi7f421272020-12-07 11:24:11 -08003993 debugfs_create_bool("model_ok", 0444, de, &chip->model_ok);
AleX Pelosifc6f66d2021-01-12 18:14:48 -08003994 debugfs_create_file("sync_model", 0400, de, chip,
3995 &debug_sync_model_fops);
Ken Tsou8acade12020-07-09 03:17:35 +08003996
AleX Pelosifed7fb12020-11-10 01:22:22 -08003997 /* capacity drift fixup, one of MAX1720X_DA_VER_* */
3998 debugfs_create_u32("algo_ver", 0644, de, &chip->drift_data.algo_ver);
AleX Pelosifc6f66d2021-01-12 18:14:48 -08003999
AleX Pelosi45558f82021-01-12 00:34:09 -08004000 /* new debug interface */
4001 debugfs_create_u32("address", 0600, de, &chip->debug_reg_address);
4002 debugfs_create_file("data", 0600, de, chip, &debug_reg_data_fops);
AleX Pelosifed7fb12020-11-10 01:22:22 -08004003
Jenny Hof98812c2021-06-11 16:35:53 +08004004 /* dump all registers */
4005 debugfs_create_file("registers", 0444, de, chip, &debug_reg_all_fops);
4006
Jenny Ho03a73aa2022-06-19 01:17:32 +00004007 if (chip->regmap_nvram.regmap)
4008 debugfs_create_file("nv_registers", 0444, de, chip, &debug_nvreg_all_fops);
4009
Jenny Ho76e43d92022-04-29 06:05:30 +08004010 /* reset fg eeprom data for debugging */
Jenny Ho03a73aa2022-06-19 01:17:32 +00004011 if (chip->gauge_type == MAX_M5_GAUGE_TYPE) {
4012 debugfs_create_file("cnhs_reset", 0400, de, chip, &debug_reset_cnhs_fops);
4013 debugfs_create_file("gmsr_reset", 0400, de, chip, &debug_reset_gmsr_fops);
4014 }
Jenny Ho76e43d92022-04-29 06:05:30 +08004015
AleX Pelosi9e8633f2022-05-06 18:21:12 +00004016 /* capacity fade */
4017 debugfs_create_u32("bhi_fcn_count", 0644, de, &chip->bhi_fcn_count);
4018
Ken Tsou8acade12020-07-09 03:17:35 +08004019 return 0;
4020}
4021
4022static u16 max1720x_read_rsense(const struct max1720x_chip *chip)
4023{
AleX Pelosi357da862021-01-11 12:18:19 -08004024 u32 rsense_default = 500;
4025 int dt_rsense, ret;
Ken Tsou8acade12020-07-09 03:17:35 +08004026 u16 rsense = 0;
Ken Tsou8acade12020-07-09 03:17:35 +08004027
AleX Pelosi357da862021-01-11 12:18:19 -08004028 ret = of_property_read_u32(chip->dev->of_node, "maxim,rsense-default",
4029 &rsense_default);
4030 dt_rsense = ret == 0;
4031
4032 /* read from NVRAM if present */
Ken Tsou8acade12020-07-09 03:17:35 +08004033 if (chip->regmap_nvram.regmap) {
Ken Tsou8acade12020-07-09 03:17:35 +08004034
4035 ret = REGMAP_READ(&chip->regmap_nvram, MAX1720X_NRSENSE, &rsense);
AleX Pelosi357da862021-01-11 12:18:19 -08004036 if (ret == 0 && dt_rsense && rsense != rsense_default) {
4037 dev_warn(chip->dev, "RSense %d, forcing to %d uOhm\n",
4038 rsense * 10, rsense_default * 10);
4039
Ken Tsou8acade12020-07-09 03:17:35 +08004040 rsense = rsense_default;
Ken Tsou8acade12020-07-09 03:17:35 +08004041 }
4042 }
4043
4044 if (!rsense)
AleX Pelosi357da862021-01-11 12:18:19 -08004045 rsense = rsense_default;
Ken Tsou8acade12020-07-09 03:17:35 +08004046
4047 return rsense;
4048}
4049
4050/*
4051 * The BCNT, QHQH and QHCA for 17202 modify these common registers
4052 * 0x18C, 0x18D, 0x18E, 0x18F, 0x1B2, 0x1B4 which will default to 0 after
4053 * the recovery procedure. The map changes the content of 0x1C4, 0x1C5 which
4054 * are not used (and should be 0 unless used by a future version of SW) as well
4055 * as 0x1CD, 0x1CE used for nManfctrName1/2 which might change. 0x1DF is the
4056 * INI checksum that will change with updates and cannot be used for this test.
4057 * The only register left is 0x1D7 (MAX1730X_NPROTCFG), that is the register
4058 * that the code will used to determine the corruption.
4059 */
4060static int max1730x_check_prot(struct max1720x_chip *chip, u16 devname)
4061{
4062 int needs_recall = 0;
4063 u16 nprotcfg;
4064 int ret;
4065
4066 /* check protection registers */
4067 ret = REGMAP_READ(&chip->regmap_nvram, MAX1730X_NPROTCFG, &nprotcfg);
4068 if (ret < 0)
4069 return -EIO;
4070
4071 if (devname == MAX1730X_GAUGE_PASS1)
4072 needs_recall = (nprotcfg != MAX1730X_NPROTCFG_PASS1);
4073 else /* pass2 */
4074 needs_recall = (nprotcfg != MAX1730X_NPROTCFG_PASS2);
4075
4076 return needs_recall;
4077}
4078
4079static int max17x0x_nvram_recall(struct max1720x_chip *chip)
4080{
4081 REGMAP_WRITE(&chip->regmap,
4082 MAX17XXX_COMMAND,
4083 MAX17XXX_COMMAND_NV_RECALL);
4084 msleep(MAX17X0X_TPOR_MS);
4085 return 0;
4086}
4087
4088/* TODO: move to google/max1730x_battery.c, enable with build config */
4089static int max1730x_fixups(struct max1720x_chip *chip)
4090{
4091 int ret;
4092
4093 struct device_node *node = chip->dev->of_node;
4094 bool write_back = false, write_ndata = false;
4095 const u16 val = 0x280B;
4096 u16 ndata = 0, bak = 0;
4097
4098 /* b/123026365 */
4099 if (of_property_read_bool(node, "maxim,enable-nv-check")) {
4100 const u16 devname = (chip->devname >> 4);
4101 int needs_recall;
4102
4103 needs_recall = max1730x_check_prot(chip, devname);
4104 if (needs_recall < 0) {
4105 dev_err(chip->dev, "error reading fg NV configuration\n");
4106 } else if (needs_recall == 0) {
4107 /* all good.. */
4108 } else if (devname == MAX1730X_GAUGE_PASS1) {
4109 dev_err(chip->dev, "***********************************************\n");
4110 dev_err(chip->dev, "WARNING: need to restore FG NV configuration to\n");
4111 dev_err(chip->dev, "default values. THE DEVICE WILL LOOSE POWER.\n");
4112 dev_err(chip->dev, "*******************************************\n");
4113 msleep(MSEC_PER_SEC);
4114 REGMAP_WRITE(&chip->regmap, MAX17XXX_COMMAND,
4115 MAX1720X_COMMAND_HARDWARE_RESET);
4116 msleep(MAX17X0X_TPOR_MS);
4117 } else {
4118 dev_err(chip->dev, "Restoring FG NV configuration to sane values\n");
4119
4120 if (!chip->needs_reset) {
4121 ret = max17x0x_nvram_recall(chip);
4122 if (ret == 0)
4123 chip->needs_reset = true;
4124 }
4125
4126 REGMAP_WRITE(&chip->regmap_nvram,
4127 MAX1730X_NPROTCFG,
4128 MAX1730X_NPROTCFG_PASS2);
4129 }
4130 } else {
4131 dev_err(chip->dev, "nv-check disabled\n");
4132 }
4133
4134 /* b/122605202 */
4135 ret = REGMAP_READ(&chip->regmap_nvram, MAX1730X_NVPRTTH1, &ndata);
4136 if (ret == 0)
4137 ret = REGMAP_READ(&chip->regmap, MAX1730X_NVPRTTH1BAK, &bak);
4138 if (ret < 0)
4139 return -EIO;
4140
4141 if (ndata == MAX1730X_NVPRTTH1_CHARGING)
4142 write_back = (bak != val);
4143 else
4144 write_ndata = (ndata != val);
4145
4146 if (write_back || write_ndata) {
4147 ret = REGMAP_WRITE(&chip->regmap,
4148 MAX1730X_NVPRTTH1BAK, val);
4149 if (ret == 0)
4150 ret = REGMAP_WRITE(&chip->regmap_nvram,
4151 MAX1730X_NVPRTTH1, val);
4152 if (ret == 0)
4153 ret = REGMAP_WRITE(&chip->regmap,
4154 MAX1730X_NVPRTTH1BAK, val);
4155 }
4156
4157 if (ret < 0)
4158 dev_info(chip->dev, "failed to update 0x0D6=%x 0x1D0=%x to %x (%d)\n",
4159 bak, ndata, val, ret);
4160 else if (write_back)
4161 dev_info(chip->dev, "0x0D6=%x 0x1D0=%x updated to %x (%d)\n",
4162 bak, ndata, val, ret);
4163 else if (write_ndata)
4164 dev_info(chip->dev, "0x1D0=%x updated to %x (%d)\n",
4165 ndata, val, ret);
4166
4167 return ret;
4168}
4169
4170static int max17x0x_dump_param(struct max1720x_chip *chip)
4171{
4172 int ret;
4173 u16 data;
4174
4175 ret = max17x0x_reg_read(&chip->regmap, MAX17X0X_TAG_cnfg,
4176 &chip->RConfig);
4177 if (ret < 0)
4178 return ret;
4179
4180 dev_info(chip->dev, "Config: 0x%04x\n", chip->RConfig);
4181
4182 ret = REGMAP_READ(&chip->regmap, MAX1720X_ICHGTERM, &data);
4183 if (ret < 0)
4184 return ret;
4185
4186 dev_info(chip->dev, "IChgTerm: %d\n",
4187 reg_to_micro_amp(data, chip->RSense));
4188
4189 ret = REGMAP_READ(&chip->regmap, MAX1720X_VEMPTY, &data);
4190 if (ret < 0)
4191 return ret;
4192
4193 dev_info(chip->dev, "VEmpty: VE=%dmV VR=%dmV\n",
4194 reg_to_vempty(data), reg_to_vrecovery(data));
4195
4196 return 0;
4197}
4198
4199static int max1720x_clear_por(struct max1720x_chip *chip)
4200{
4201 u16 data;
4202 int ret;
4203
4204 ret = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &data);
4205 if (ret < 0)
4206 return ret;
4207
4208 if ((data & MAX1720X_STATUS_POR) == 0)
4209 return 0;
4210
4211 return regmap_update_bits(chip->regmap.regmap,
4212 MAX1720X_STATUS,
4213 MAX1720X_STATUS_POR,
4214 0x0);
4215}
4216
AleX Pelosi7f421272020-12-07 11:24:11 -08004217/* read state from fg (if needed) and set the next update field */
4218static int max1720x_set_next_update(struct max1720x_chip *chip)
4219{
Jenny Ho7c84e052021-07-09 17:43:33 +08004220 int rc;
4221 u16 reg_cycle;
AleX Pelosi7f421272020-12-07 11:24:11 -08004222
Jenny Hoea0331e2021-06-22 17:38:27 +08004223 /* do not save data when battery ID not clearly */
Jenny Ho316abea2021-06-22 17:38:27 +08004224 if (chip->batt_id == DEFAULT_BATTERY_ID)
4225 return 0;
4226
Jenny Ho7c84e052021-07-09 17:43:33 +08004227 rc = REGMAP_READ(&chip->regmap, MAX1720X_CYCLES, &reg_cycle);
4228 if (rc < 0)
4229 return rc;
AleX Pelosi7f421272020-12-07 11:24:11 -08004230
Jenny Ho7c84e052021-07-09 17:43:33 +08004231 if (chip->model_next_update && reg_cycle < chip->model_next_update)
AleX Pelosi7f421272020-12-07 11:24:11 -08004232 return 0;
4233
4234 /* read new state from Fuel gauge, save to storage if needed */
4235 rc = max_m5_model_read_state(chip->model_data);
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004236 if (rc == 0) {
4237 rc = max_m5_model_check_state(chip->model_data);
4238 if (rc < 0) {
4239 pr_debug("%s: fg model state is corrupt rc=%d\n",
4240 __func__, rc);
4241 return -EINVAL;
4242 }
4243 }
4244
AleX Pelosi7f421272020-12-07 11:24:11 -08004245 if (rc == 0 && chip->model_next_update)
4246 rc = max_m5_save_state_data(chip->model_data);
4247 if (rc == 0)
Jenny Ho7c84e052021-07-09 17:43:33 +08004248 chip->model_next_update = (reg_cycle + (1 << 6)) &
AleX Pelosi7f421272020-12-07 11:24:11 -08004249 ~((1 << 6) - 1);
4250
Jenny Ho7c84e052021-07-09 17:43:33 +08004251 pr_debug("%s: reg_cycle=%d next_update=%d rc=%d\n", __func__,
4252 reg_cycle, chip->model_next_update, rc);
AleX Pelosi7f421272020-12-07 11:24:11 -08004253
4254 return 0;
4255}
4256
Ken Tsou8acade12020-07-09 03:17:35 +08004257static int max1720x_model_load(struct max1720x_chip *chip)
4258{
4259 int ret;
4260
4261 /* retrieve model state from permanent storage only on boot */
AleX Pelosi76b63502020-11-03 16:49:44 -08004262 if (!chip->model_state_valid) {
Ken Tsou8acade12020-07-09 03:17:35 +08004263
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004264 /*
4265 * retrieve state from storage: retry on -EAGAIN as long as
4266 * model_reload > _IDLE
4267 */
Ken Tsou8acade12020-07-09 03:17:35 +08004268 ret = max_m5_load_state_data(chip->model_data);
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004269 if (ret == -EAGAIN)
4270 return -EAGAIN;
4271 if (ret < 0)
4272 dev_warn(chip->dev, "Load Model Using Default State (%d)\n",
Ken Tsou8acade12020-07-09 03:17:35 +08004273 ret);
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004274
4275 /* use the state from the DT when GMSR is invalid */
Ken Tsou8acade12020-07-09 03:17:35 +08004276 }
4277
4278 /* failure on the gauge: retry as long as model_reload > IDLE */
4279 ret = max_m5_load_gauge_model(chip->model_data);
4280 if (ret < 0) {
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004281 dev_err(chip->dev, "Load Model Failed ret=%d\n", ret);
Ken Tsou8acade12020-07-09 03:17:35 +08004282 return -EAGAIN;
4283 }
4284
AleX Pelosifed7fb12020-11-10 01:22:22 -08004285 /* fix capacity outliers algo */
4286 ret = max_m5_fixup_outliers(&chip->drift_data, chip->model_data);
4287 if (ret < 0)
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004288 dev_err(chip->dev, "Load Model fixing drift data rc=%d\n", ret);
AleX Pelosifed7fb12020-11-10 01:22:22 -08004289
AleX Pelosi7f421272020-12-07 11:24:11 -08004290 /* mark model state as "safe" */
Ken Tsou8acade12020-07-09 03:17:35 +08004291 chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
AleX Pelosi76b63502020-11-03 16:49:44 -08004292 chip->model_state_valid = true;
Ken Tsou8acade12020-07-09 03:17:35 +08004293 return 0;
4294}
4295
4296static void max1720x_model_work(struct work_struct *work)
4297{
4298 struct max1720x_chip *chip = container_of(work, struct max1720x_chip,
4299 model_work.work);
AleX Pelosi7f421272020-12-07 11:24:11 -08004300 bool new_model = false;
Jenny Ho7c84e052021-07-09 17:43:33 +08004301 u16 reg_cycle;
4302 int rc;
Ken Tsou8acade12020-07-09 03:17:35 +08004303
4304 if (!chip->model_data)
4305 return;
4306
Ken Tsou8acade12020-07-09 03:17:35 +08004307 mutex_lock(&chip->model_lock);
4308
AleX Pelosi7f421272020-12-07 11:24:11 -08004309 /* set model_reload to the #attempts, might change cycle count */
Ken Tsou8acade12020-07-09 03:17:35 +08004310 if (chip->model_reload >= MAX_M5_LOAD_MODEL_REQUEST) {
4311
4312 rc = max1720x_model_load(chip);
4313 if (rc == 0) {
4314 rc = max1720x_clear_por(chip);
AleX Pelosi7f421272020-12-07 11:24:11 -08004315
AleX Pelosi962aedf2021-01-07 15:39:43 -08004316 dev_info(chip->dev, "Model OK, Clear Power-On Reset (%d)\n",
4317 rc);
Ken Tsou8acade12020-07-09 03:17:35 +08004318
4319 /* TODO: keep trying to clear POR if the above fail */
Jenny Hoc6bc5882021-02-18 09:21:21 +08004320
4321 max1720x_restore_battery_cycle(chip);
Jenny Ho7c84e052021-07-09 17:43:33 +08004322 rc = REGMAP_READ(&chip->regmap, MAX1720X_CYCLES, &reg_cycle);
4323 if (rc == 0 && reg_cycle >= 0) {
Jenny Hoc6bc5882021-02-18 09:21:21 +08004324 chip->model_reload = MAX_M5_LOAD_MODEL_IDLE;
4325 chip->model_ok = true;
4326 new_model = true;
4327 /* saved new value in max1720x_set_next_update */
Jenny Ho7c84e052021-07-09 17:43:33 +08004328 chip->model_next_update = reg_cycle > 0 ? reg_cycle - 1 : 0;
Jenny Hoc6bc5882021-02-18 09:21:21 +08004329 }
Ken Tsou8acade12020-07-09 03:17:35 +08004330 } else if (rc != -EAGAIN) {
4331 chip->model_reload = MAX_M5_LOAD_MODEL_DISABLED;
AleX Pelosi7f421272020-12-07 11:24:11 -08004332 chip->model_ok = false;
AleX Pelosi962aedf2021-01-07 15:39:43 -08004333 } else if (chip->model_reload > MAX_M5_LOAD_MODEL_IDLE) {
Ken Tsou8acade12020-07-09 03:17:35 +08004334 chip->model_reload -= 1;
4335 }
4336 }
4337
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004338 /* b/171741751, fix capacity drift (if POR is cleared) */
4339 if (max1720x_check_drift_enabled(&chip->drift_data))
4340 max1720x_fixup_capacity(chip, chip->cap_estimate.cable_in);
4341
Ken Tsou8acade12020-07-09 03:17:35 +08004342 if (chip->model_reload >= MAX_M5_LOAD_MODEL_REQUEST) {
4343 const unsigned long delay = msecs_to_jiffies(60 * 1000);
4344
Jenny Ho7e578102021-05-24 18:22:55 +08004345 mod_delayed_work(system_wq, &chip->model_work, delay);
Ken Tsou8acade12020-07-09 03:17:35 +08004346 }
4347
AleX Pelosi962aedf2021-01-07 15:39:43 -08004348 if (new_model) {
4349 dev_info(chip->dev, "FG Model OK, ver=%d cap_lsb=%d next_update=%d\n",
4350 max_m5_fg_model_version(chip->model_data),
4351 max_m5_cap_lsb(chip->model_data),
4352 chip->model_next_update);
AleX Pelosi7f421272020-12-07 11:24:11 -08004353 power_supply_changed(chip->psy);
AleX Pelosi962aedf2021-01-07 15:39:43 -08004354 }
AleX Pelosi7f421272020-12-07 11:24:11 -08004355
Ken Tsou8acade12020-07-09 03:17:35 +08004356 mutex_unlock(&chip->model_lock);
4357}
4358
Jenny Ho39b2def2022-03-02 18:18:13 +08004359
4360static int max17201_init_rc_switch(struct max1720x_chip *chip)
4361{
4362 int ret = 0;
4363
4364 if (chip->gauge_type != MAX_M5_GAUGE_TYPE)
4365 return -EINVAL;
4366
4367 chip->rc_switch.enable = of_property_read_bool(chip->dev->of_node, "maxim,rc-enable");
4368
4369 ret = of_property_read_u32(chip->dev->of_node, "maxim,rc-soc", &chip->rc_switch.soc);
4370 if (ret < 0)
4371 return ret;
4372
4373 ret = of_property_read_u32(chip->dev->of_node, "maxim,rc-temp", &chip->rc_switch.temp);
4374 if (ret < 0)
4375 return ret;
4376
4377 ret = of_property_read_u16(chip->batt_node, "maxim,rc1-tempco", &chip->rc_switch.rc1_tempco);
4378 if (ret < 0)
4379 return ret;
4380
4381 /* Same as INI value */
4382 ret = of_property_read_u16(chip->batt_node, "maxim,rc2-tempco", &chip->rc_switch.rc2_tempco);
4383 if (ret < 0)
4384 return ret;
4385
4386 /* Same as INI value */
4387 ret = of_property_read_u16(chip->batt_node, "maxim,rc2-learncfg", &chip->rc_switch.rc2_learncfg);
4388 if (ret < 0)
4389 return ret;
4390
4391 chip->rc_switch.available = true;
4392
4393 dev_warn(chip->dev, "rc_switch: enable:%d soc/temp:%d/%d tempco_rc1/rc2:%#x/%#x\n",
4394 chip->rc_switch.enable, chip->rc_switch.soc, chip->rc_switch.temp,
4395 chip->rc_switch.rc1_tempco, chip->rc_switch.rc2_tempco);
4396
4397 if (chip->rc_switch.enable)
4398 schedule_delayed_work(&chip->rc_switch.switch_work, msecs_to_jiffies(60 * 1000));
4399
4400 return 0;
4401}
4402
4403#define RC_WORK_TIME_MS 60 * 1000
4404#define RC_WORK_TIME_QUICK_MS 5 * 1000
4405static void max1720x_rc_work(struct work_struct *work)
4406{
4407 struct max1720x_chip *chip = container_of(work, struct max1720x_chip,
4408 rc_switch.switch_work.work);
4409 int interval = RC_WORK_TIME_MS;
4410 u16 data, learncfg;
4411 bool to_rc1, to_rc2;
4412 int ret, soc, temp;
4413
4414 if (!chip->rc_switch.available || !chip->rc_switch.enable)
4415 return;
4416
4417 /* Read SOC */
4418 ret = REGMAP_READ(&chip->regmap, MAX_M5_REPSOC, &data);
4419 if (ret < 0)
4420 goto reschedule;
4421
4422 soc = (data >> 8) & 0x00FF;
4423
4424 /* Read Temperature */
4425 ret = max17x0x_reg_read(&chip->regmap, MAX17X0X_TAG_temp, &data);
4426 if (ret < 0)
4427 goto reschedule;
4428
4429 temp = reg_to_deci_deg_cel(data);
4430
4431 /* Read LearnCfg */
4432 ret = REGMAP_READ(&chip->regmap, MAX_M5_LEARNCFG, &learncfg);
4433 if (ret < 0)
4434 goto reschedule;
4435
4436 /* Disable LearnCfg.LearnTCO */
4437 if (learncfg & MAX_M5_LEARNCFG_LEARNTCO_CLEAR) {
4438 learncfg = MAX_M5_LEARNCFG_LEARNTCO_CLR(learncfg);
4439 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_LEARNCFG, learncfg);
4440 if (ret < 0)
4441 dev_warn(chip->dev, "Unable to clear LearnTCO\n");
4442 }
4443
4444 to_rc1 = soc < chip->rc_switch.soc || temp < chip->rc_switch.temp;
4445 to_rc2 = soc >= chip->rc_switch.soc && temp >= chip->rc_switch.temp;
4446
4447 if (to_rc1 && ((learncfg & MAX_M5_LEARNCFG_RC_VER) == MAX_M5_LEARNCFG_RC2)) {
4448 /*
4449 * 1: set LearnCfg.LearnRComp = 0
4450 * 2: load TempCo value from RC1 INI file
4451 * 3: set LearnCfg.RCx = 0
4452 */
4453 learncfg = MAX_M5_LEARNCFG_LEARNRCOMP_CLR(learncfg);
4454 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_LEARNCFG, learncfg);
4455
4456 if (ret == 0)
4457 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_TEMPCO, chip->rc_switch.rc1_tempco);
4458
4459 learncfg = MAX_M5_LEARNCFG_RC_VER_CLR(learncfg);
4460 if (ret == 0)
4461 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_LEARNCFG, learncfg);
4462
4463 gbms_logbuffer_prlog(chip->monitor_log, LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
4464 "%s to RC1. ret=%d soc=%d temp=%d tempco=0x%x, learncfg=0x%x",
4465 __func__, ret, soc, temp, chip->rc_switch.rc1_tempco, learncfg);
4466
4467 } else if (to_rc2 && ((learncfg & MAX_M5_LEARNCFG_RC_VER) == MAX_M5_LEARNCFG_RC1)) {
4468 /*
4469 * 1: load LearnCfg.LearnRComp from RC2 INI value
4470 * 2: load TempCo value from RC2 INI value
4471 * 3: set LearnCfg.RCx = 1
4472 */
4473
4474 learncfg |= (chip->rc_switch.rc2_learncfg & MAX_M5_LEARNCFG_LEARNRCOMP);
4475 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_LEARNCFG, learncfg);
4476
4477 if (ret == 0)
4478 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_TEMPCO, chip->rc_switch.rc2_tempco);
4479
4480 learncfg = MAX_M5_LEARNCFG_RC_VER_SET(learncfg);
4481 if (ret == 0)
4482 ret = REGMAP_WRITE(&chip->regmap, MAX_M5_LEARNCFG, learncfg);
4483
4484 gbms_logbuffer_prlog(chip->monitor_log, LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
4485 "%s to RC2. ret=%d soc=%d temp=%d tempco=0x%x, learncfg=0x%x",
4486 __func__, ret, soc, temp, chip->rc_switch.rc2_tempco, learncfg);
4487 }
4488
4489reschedule:
4490 if (ret != 0) {
4491 interval = RC_WORK_TIME_QUICK_MS;
4492 gbms_logbuffer_prlog(chip->monitor_log, LOGLEVEL_WARNING, 0, LOGLEVEL_INFO,
4493 "%s didn't finish. ret=%d", __func__, ret);
4494 }
4495
4496 mod_delayed_work(system_wq, &chip->rc_switch.switch_work, msecs_to_jiffies(interval));
4497}
4498
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004499static int read_chip_property_u32(const struct max1720x_chip *chip,
4500 char *property, u32 *data32)
4501{
4502 int ret;
4503
4504 if (chip->batt_node) {
4505 ret = of_property_read_u32(chip->batt_node, property, data32);
4506 if (ret == 0)
4507 return ret;
4508 }
4509
4510 return of_property_read_u32(chip->dev->of_node, property, data32);
4511}
4512
AleX Pelosi962aedf2021-01-07 15:39:43 -08004513/* fix capacity drift after loading the model */
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004514static int max17201_init_fix_capacity(struct max1720x_chip *chip)
4515{
4516 struct max1720x_drift_data *ddata = &chip->drift_data;
4517 u32 data32 = 0;
4518 u16 data16;
4519 int ret;
4520
4521 ret = gbms_storage_read(GBMS_TAG_CMPC, &data16, sizeof(data16));
4522 if (ret == -EPROBE_DEFER)
4523 return -EPROBE_DEFER;
4524 if (ret == 0)
4525 chip->comp_update_count = data16;
4526 else
4527 chip->comp_update_count = 0;
4528
4529 ret = gbms_storage_read(GBMS_TAG_DXAC, &data16, sizeof(data16));
4530 if (ret == -EPROBE_DEFER)
4531 return -EPROBE_DEFER;
4532 if (ret == 0)
4533 chip->dxacc_update_count = data16;
4534 else
4535 chip->dxacc_update_count = 0;
4536
4537 /* device dependent values */
4538 ddata->rsense = chip->RSense;
AleX Pelosi962aedf2021-01-07 15:39:43 -08004539 /* update design_capacity after loading the model if not set in dt */
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004540 ret = of_property_read_u32(chip->dev->of_node, "maxim,capacity-design",
4541 &data32);
4542 if (ret < 0) {
4543 ddata->design_capacity = -1;
4544 } else if (data32 != 0) {
4545 ddata->design_capacity = data32;
4546 } else if (chip->regmap_nvram.regmap) {
4547 /*
4548 * TODO: read design capacity from NVRAM if available
4549 * ret = REGMAP_READ(&chip->regmap_nvram, MAX1720X_NDESIGNCAP,
4550 * &ddata->design_capacity);
4551 */
4552 ret = REGMAP_READ(&chip->regmap, MAX1720X_DESIGNCAP,
4553 &ddata->design_capacity);
4554 if (ret < 0)
4555 return -EPROBE_DEFER;
4556
4557 /* add retries? */
4558 }
4559
4560 /*
4561 * chemistry dependent codes:
4562 * NOTE: ->batt_node is initialized in *_handle_dt_shadow_config
4563 */
4564 ret = read_chip_property_u32(chip, "maxim,capacity-rcomp0", &data32);
4565 if (ret < 0)
4566 ddata->ini_rcomp0 = -1;
4567 else
4568 ddata->ini_rcomp0 = data32;
4569
4570 ret = read_chip_property_u32(chip, "maxim,capacity-tempco", &data32);
4571 if (ret < 0)
4572 ddata->ini_tempco = -1;
4573 else
4574 ddata->ini_tempco = data32;
4575
4576 ret = of_property_read_u32(chip->dev->of_node, "maxim,capacity-stable",
4577 &data32);
4578 if (ret < 0)
4579 ddata->cycle_stable = BATTERY_DEFAULT_CYCLE_STABLE;
4580 else
4581 ddata->cycle_stable = data32;
4582
4583 ret = of_property_read_u32(chip->dev->of_node, "maxim,capacity-fade",
4584 &data32);
4585 if (ret < 0)
4586 ddata->cycle_fade = BATTERY_DEFAULT_CYCLE_FADE;
4587 else
4588 ddata->cycle_fade = data32;
4589
4590 ret = of_property_read_u32(chip->dev->of_node, "maxim,capacity-band",
4591 &data32);
4592 if (ret < 0) {
4593 ddata->cycle_band = BATTERY_DEFAULT_CYCLE_BAND;
4594 } else {
4595 ddata->cycle_band = data32;
4596 if (ddata->cycle_band > BATTERY_MAX_CYCLE_BAND)
4597 ddata->cycle_band = BATTERY_MAX_CYCLE_BAND;
4598 }
4599
AleX Pelosi962aedf2021-01-07 15:39:43 -08004600 /*
4601 * Set to force loading the model with corresponding algo-version.
4602 * MW A0+ MW-A0 should use MAX1720X_DA_VER_ORIG while and MW-A1 should
4603 * use MAX1720X_DA_VER_MWA1 for RC1 or MAX1720X_DA_VER_NONE for RC2.
4604 * MW-A2 should use MAX1720X_DA_VER_NONE for RC1 and RC2.
4605 * Not used for max1720x and max1730x.
4606 */
4607 if (max_m5_check_devname(chip->devname) ) {
4608 ret = of_property_read_u32(chip->dev->of_node,
4609 "maxim,algo-version",
4610 &data32);
4611 if (ret < 0 || data32 > MAX1720X_DA_VER_MWA2)
4612 ddata->algo_ver = MAX1720X_DA_VER_NONE;
4613 else
4614 ddata->algo_ver = data32;
4615 } else {
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004616 ddata->algo_ver = MAX1720X_DA_VER_ORIG;
AleX Pelosi962aedf2021-01-07 15:39:43 -08004617 }
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004618
4619 ret = read_chip_property_u32(chip, "maxim,capacity-filtercfg", &data32);
4620 if (ret < 0)
4621 ddata->ini_filtercfg = -1;
4622 else
4623 ddata->ini_filtercfg = data32;
4624
AleX Pelosi962aedf2021-01-07 15:39:43 -08004625 if (ddata->ini_filtercfg != -1)
4626 dev_info(chip->dev, "ini_filtercfg=0x%x\n",
4627 ddata->ini_filtercfg);
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004628
4629 return 0;
4630}
4631
Jenny Ho81146ba2021-06-29 17:17:25 +08004632static int max1720x_check_config(struct max1720x_chip *chip)
4633{
4634 u16 data;
4635 int ret;
4636
4637 ret = REGMAP_READ(&chip->regmap, MAX1720X_CONFIG, &data);
4638 if (ret == 0 && (data & MAX1720X_CONFIG_TEN) == 0)
4639 return -EINVAL;
4640
4641 return 0;
4642}
4643
AleX Pelosi27289972021-07-01 11:51:56 -07004644static int max1720x_log_event(struct max1720x_chip *chip, gbms_tag_t tag)
4645{
4646 u8 event_count;
4647 int ret = 0;
4648
4649 ret = gbms_storage_read(tag, &event_count, sizeof(event_count));
4650 if (ret < 0)
4651 return ret;
4652
4653 /* max count */
4654 if (event_count == 0xFE)
4655 return 0;
4656
4657 /* initial value */
4658 if (event_count == 0xFF)
4659 event_count = 1;
4660 else
4661 event_count++;
4662
4663 ret = gbms_storage_write(tag, &event_count, sizeof(event_count));
4664 if (ret < 0)
4665 return ret;
4666
4667 dev_info(chip->dev, "tag:0x%X, event_count:%d\n", tag, event_count);
4668
4669 return 0;
4670}
4671
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004672/* handle recovery of FG state */
4673static int max1720x_init_max_m5(struct max1720x_chip *chip)
4674{
4675 int ret;
4676
Jenny Ho7c691da2021-05-19 06:15:54 +08004677 if (!max_m5_fg_model_check_version(chip->model_data)) {
4678 if (max_m5_needs_reset_model_data(chip->model_data)) {
4679 ret = max_m5_reset_state_data(chip->model_data);
4680 if (ret < 0)
4681 dev_err(chip->dev, "GMSR: failed to erase RC2 saved model data"
4682 " ret=%d\n", ret);
4683 else
4684 dev_warn(chip->dev, "GMSR: RC2 model data erased\n");
4685 }
4686
AleX Pelosi27289972021-07-01 11:51:56 -07004687 /* this is expected */
Jenny Ho7c691da2021-05-19 06:15:54 +08004688 ret = max1720x_full_reset(chip);
4689
4690 dev_warn(chip->dev, "FG Version Changed, Reset (%d), Will Reload\n",
4691 ret);
4692 return 0;
4693 }
4694
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004695 /* TODO add retries */
4696 ret = max_m5_model_read_state(chip->model_data);
4697 if (ret < 0) {
4698 dev_err(chip->dev, "FG Model Error (%d)\n", ret);
4699 return -EPROBE_DEFER;
4700 }
4701
AleX Pelosi27289972021-07-01 11:51:56 -07004702 /* this is a real failure and must be logged */
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004703 ret = max_m5_model_check_state(chip->model_data);
4704 if (ret < 0) {
AleX Pelosi27289972021-07-01 11:51:56 -07004705 int rret, sret = -1;
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004706
AleX Pelosi27289972021-07-01 11:51:56 -07004707 rret = max1720x_full_reset(chip);
4708 if (rret == 0)
4709 sret = max_m5_model_read_state(chip->model_data);
4710
4711 dev_err(chip->dev, "FG State Corrupt (%d), Reset (%d), State (%d) Will reload\n",
4712 ret, rret, sret);
4713
4714 ret = max1720x_log_event(chip, GBMS_TAG_SELC);
4715 if (ret < 0)
4716 dev_err(chip->dev, "Cannot log the event (%d)\n", ret);
4717
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004718 return 0;
4719 }
4720
Jenny Ho81146ba2021-06-29 17:17:25 +08004721 ret = max1720x_check_config(chip);
4722 if (ret < 0) {
4723 ret = max1720x_full_reset(chip);
4724 if (ret == 0)
4725 ret = max_m5_model_read_state(chip->model_data);
4726
4727 dev_err(chip->dev, "Invalid config data, Reset (%d), Will reload\n",
4728 ret);
AleX Pelosi27289972021-07-01 11:51:56 -07004729
4730 ret = max1720x_log_event(chip, GBMS_TAG_CELC);
4731 if (ret < 0)
4732 dev_err(chip->dev, "Cannot log the event (%d)\n", ret);
4733
Jenny Ho81146ba2021-06-29 17:17:25 +08004734 return 0;
4735 }
4736
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004737 ret = max1720x_set_next_update(chip);
4738 if (ret < 0)
4739 dev_warn(chip->dev, "Error on Next Update, Will retry\n");
4740
4741 dev_info(chip->dev, "FG Model OK, ver=%d cap_lsb=%d next_update=%d\n",
4742 max_m5_model_read_version(chip->model_data),
4743 max_m5_cap_lsb(chip->model_data),
4744 chip->model_next_update);
4745
4746 chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
4747 chip->model_state_valid = true;
4748 chip->model_ok = true;
4749 return 0;
4750}
4751
Ken Tsou8acade12020-07-09 03:17:35 +08004752static int max1720x_init_chip(struct max1720x_chip *chip)
4753{
4754 int ret;
4755 u8 vreg, vpor;
4756 u16 data = 0, tmp;
Jenny Ho6a391fd2022-08-10 23:33:14 +00004757 bool force_recall = false;
Ken Tsou8acade12020-07-09 03:17:35 +08004758
4759 if (of_property_read_bool(chip->dev->of_node, "maxim,force-hard-reset"))
4760 max1720x_full_reset(chip);
4761
4762 ret = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &data);
4763 if (ret < 0)
4764 return -EPROBE_DEFER;
Jenny Ho6a391fd2022-08-10 23:33:14 +00004765 chip->por = (data & MAX1720X_STATUS_POR) != 0;
4766 if (chip->por && chip->regmap_nvram.regmap) {
Ken Tsou8acade12020-07-09 03:17:35 +08004767 dev_err(chip->dev, "Recall: POR bit is set\n");
4768 force_recall = true;
4769 }
4770
4771 /* TODO: disable with maxim,fix-ignore-zero-rsense */
4772 chip->RSense = max1720x_read_rsense(chip);
4773 if (chip->RSense == 0) {
4774 dev_err(chip->dev, "Recall: RSense value 0 micro Ohm\n");
4775 force_recall = true;
4776 }
4777
4778 /* read por force recall and reset when version is the por */
4779 ret = max17x0x_read_dt_version_por(chip->dev->of_node,
4780 chip->gauge_type, &vreg, &vpor);
4781 if (ret == 0) {
4782 ret = REGMAP_READ(&chip->regmap_nvram, vreg, &tmp);
4783 if ((ret == 0) && (vpor == (tmp & 0x00ff))) {
4784 dev_err(chip->dev, "Recall: POR version %d\n", vpor);
4785 force_recall = true;
4786 }
4787 }
4788
4789 /* b/129384855 fix mismatch between pack INI file and overrides */
4790 if (of_property_read_bool(chip->dev->of_node, "maxim,fix-vempty")) {
4791 ret = REGMAP_READ(&chip->regmap, MAX1720X_VEMPTY, &data);
4792 if ((ret == 0) && (reg_to_vrecovery(data) == 0)) {
4793 dev_err(chip->dev, "Recall: zero vrecovery\n");
4794 force_recall = true;
4795 }
4796 }
4797
4798 if (force_recall && chip->regmap_nvram.regmap) {
4799 /* debug only */
4800 ret = max17x0x_nvram_cache_init(&chip->nRAM_por,
4801 chip->gauge_type);
4802 if (ret == 0)
4803 ret = max17x0x_cache_load(&chip->nRAM_por,
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004804 &chip->regmap_nvram);
Ken Tsou8acade12020-07-09 03:17:35 +08004805 if (ret < 0) {
4806 dev_err(chip->dev, "POR: Failed to backup config\n");
4807 return -EPROBE_DEFER;
4808 }
4809
4810 dev_info(chip->dev, "Recall Battery NVRAM\n");
4811 ret = max17x0x_nvram_recall(chip);
4812 if (ret == 0)
4813 chip->needs_reset = true;
4814
4815 /* TODO: enable with maxim,fix-nagefccfg */
4816 if (chip->gauge_type == MAX1720X_GAUGE_TYPE)
4817 REGMAP_WRITE(&chip->regmap_nvram,
4818 MAX1720X_NAGEFCCFG, 0);
4819 }
4820
AleX Pelosi962aedf2021-01-07 15:39:43 -08004821 /* device dependent fixups to the registers */
Ken Tsou8acade12020-07-09 03:17:35 +08004822 if (chip->fixups_fn) {
4823 ret = chip->fixups_fn(chip);
4824 if (ret < 0) {
4825 dev_err(chip->dev, "Fixups failed (%d)\n", ret);
4826 return ret;
4827 }
4828 }
4829
4830 /* set maxim,force-batt-id in DT to not delay the probe */
4831 ret = max1720x_read_batt_id(&chip->batt_id, chip);
4832 if (ret == -EPROBE_DEFER) {
4833 if (chip->batt_id_defer_cnt) {
4834 chip->batt_id_defer_cnt -= 1;
4835 return -EPROBE_DEFER;
4836 }
4837
4838 chip->batt_id = DEFAULT_BATTERY_ID;
4839 dev_info(chip->dev, "default device battery ID = %d\n",
4840 chip->batt_id);
4841 } else {
4842 dev_info(chip->dev, "device battery RID: %d kohm\n",
4843 chip->batt_id);
4844 }
4845
AleX Pelosi962aedf2021-01-07 15:39:43 -08004846 /* fuel gauge model needs to know the batt_id */
Ken Tsou8acade12020-07-09 03:17:35 +08004847 mutex_init(&chip->model_lock);
AleX Pelosi962aedf2021-01-07 15:39:43 -08004848
4849 /*
4850 * The behavior of the drift workaround changes with the capacity
4851 * learning algo used in the part. Integrated FG might have
4852 * configurable capacity learning.
4853 */
4854 ret = max17201_init_fix_capacity(chip);
4855 if (ret < 0)
4856 dev_err(chip->dev, "Capacity drift WAR not enabled(%d)\n", ret);
4857 /*
4858 * FG model is ony used for integrated FG (MW). Loading a model might
4859 * change the capacity drift WAR algo_ver and design_capacity.
4860 * NOTE: design_capacity used for drift might be updated after loading
4861 * a FG model.
4862 */
4863 ret = max1720x_init_model(chip);
4864 if (ret < 0)
4865 dev_err(chip->dev, "Cannot init FG model (%d)\n", ret);
4866
4867 /* dump capacity drift fixup configuration only when enabled */
4868 if (chip->drift_data.algo_ver != MAX1720X_DA_VER_NONE) {
4869 struct max1720x_drift_data *ddata = &chip->drift_data;
4870
4871 dev_info(chip->dev, "ver=%d rsns=%d cnts=%d,%d dc=%d cap_sta=%d cap_fad=%d rcomp0=0x%x tempco=0x%x\n",
4872 ddata->algo_ver, ddata->rsense,
4873 chip->comp_update_count, chip->dxacc_update_count,
4874 ddata->design_capacity, ddata->cycle_stable,
4875 ddata->cycle_fade, ddata->ini_rcomp0,
4876 ddata->ini_tempco);
4877 }
Ken Tsou8acade12020-07-09 03:17:35 +08004878
Jenny Ho39b2def2022-03-02 18:18:13 +08004879 /*
4880 * The RC change is WA for MaxCap increase abnormally b/213425610
4881 */
4882 ret = max17201_init_rc_switch(chip);
4883 if (ret < 0)
4884 chip->rc_switch.available = false;
4885
Ken Tsou8acade12020-07-09 03:17:35 +08004886 /* not needed for FG with NVRAM */
4887 ret = max17x0x_handle_dt_shadow_config(chip);
4888 if (ret == -EPROBE_DEFER)
4889 return ret;
4890
4891 ret = max17x0x_handle_dt_register_config(chip);
4892 if (ret == -EPROBE_DEFER)
4893 return ret;
4894
4895 (void) max1720x_handle_dt_nconvgcfg(chip);
Jenny Ho80a583b2021-11-15 01:46:25 +08004896 (void) max1720x_handle_dt_filtercfg(chip);
Ken Tsou8acade12020-07-09 03:17:35 +08004897
4898 /* recall, force & reset SW */
4899 if (chip->needs_reset) {
4900 max17x0x_fg_reset(chip);
4901
4902 if (chip->RSense == 0)
4903 chip->RSense = max1720x_read_rsense(chip);
4904 }
4905
4906 ret = max17x0x_dump_param(chip);
4907 if (ret < 0)
4908 return -EPROBE_DEFER;
4909 dev_info(chip->dev, "RSense value %d micro Ohm\n", chip->RSense * 10);
4910
4911 ret = REGMAP_READ(&chip->regmap, MAX1720X_STATUS, &data);
4912 if (!ret && data & MAX1720X_STATUS_BR) {
4913 dev_info(chip->dev, "Clearing Battery Removal bit\n");
4914 regmap_update_bits(chip->regmap.regmap, MAX1720X_STATUS,
4915 MAX1720X_STATUS_BR, 0x0);
4916 }
4917 if (!ret && data & MAX1720X_STATUS_BI) {
4918 dev_info(chip->dev, "Clearing Battery Insertion bit\n");
4919 regmap_update_bits(chip->regmap.regmap, MAX1720X_STATUS,
4920 MAX1720X_STATUS_BI, 0x0);
4921 }
4922
Jenny Hoc6bc5882021-02-18 09:21:21 +08004923 max1720x_restore_battery_cycle(chip);
4924
AleX Pelosi962aedf2021-01-07 15:39:43 -08004925 /* max_m5 triggers loading of the model in the irq handler on POR */
Jenny Ho6a391fd2022-08-10 23:33:14 +00004926 if (!chip->por && chip->gauge_type == MAX_M5_GAUGE_TYPE) {
AleX Pelosifc6f66d2021-01-12 18:14:48 -08004927 ret = max1720x_init_max_m5(chip);
4928 if (ret < 0)
4929 return ret;
Jenny Ho6a391fd2022-08-10 23:33:14 +00004930 } else if (chip->por && chip->gauge_type != MAX_M5_GAUGE_TYPE) {
AleX Pelosi7f421272020-12-07 11:24:11 -08004931 ret = regmap_update_bits(chip->regmap.regmap,
4932 MAX1720X_STATUS,
4933 MAX1720X_STATUS_POR, 0x0);
4934 dev_info(chip->dev, "Clearing Power-On Reset bit (%d)\n", ret);
4935 chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
Ken Tsou8acade12020-07-09 03:17:35 +08004936 }
4937
AleX Pelosi9f326fb2020-10-27 01:50:47 -07004938
Ken Tsou8acade12020-07-09 03:17:35 +08004939 max1720x_restore_battery_qh_capacity(chip);
4940
4941 return 0;
4942}
4943
4944static int max1730x_decode_sn(char *serial_number,
4945 unsigned int max,
4946 const u16 *data)
4947{
4948 int tmp, count = 0;
4949
4950 if (data[0] != 0x4257) /* "BW": DSY */
4951 return -EINVAL;
4952
4953 count += scnprintf(serial_number + count, max - count, "%02X%02X%02X",
4954 data[3] & 0xFF,
4955 data[4] & 0xFF,
4956 data[5] & 0xFF);
4957
4958 tmp = (((((data[1] >> 9) & 0x3f) + 1980) * 10000) +
4959 ((data[1] >> 5) & 0xf) * 100 + (data[1] & 0x1F));
4960 count += scnprintf(serial_number + count, max - count, "%d",
4961 tmp);
4962
4963 count += scnprintf(serial_number + count, max - count, "%c%c",
4964 data[0] >> 8, data[0] & 0xFF);
4965
4966 count += scnprintf(serial_number + count, max - count, "%c%c%c%c",
4967 data[7] >> 8,
4968 data[8] >> 8,
4969 data[9] >> 8,
4970 data[9] & 0xFF);
4971
4972 count += scnprintf(serial_number + count, max - count, "%c",
4973 data[2] & 0xFF);
4974
4975 count += scnprintf(serial_number + count, max - count, "%c%c",
4976 data[6] >> 8, data[6] & 0xFF);
Jenny Ho1744cdd2021-03-12 15:41:18 +08004977 return count;
Ken Tsou8acade12020-07-09 03:17:35 +08004978}
4979
4980static int max1720x_decode_sn(char *serial_number,
4981 unsigned int max,
4982 const u16 *data)
4983{
4984 int tmp, count = 0, shift;
4985 char cell_vendor;
4986
4987 if (data[0] == 0x5357) /* "SW": SWD */
4988 shift = 0;
4989 else if (data[0] == 0x4257) /* "BW": DSY */
4990 shift = 8;
4991 else
4992 return -EINVAL;
4993
4994 count += scnprintf(serial_number + count, max - count, "%02X%02X%02X",
4995 data[1] >> shift,
4996 data[2] >> shift,
4997 data[3] >> shift);
4998
4999 tmp = (((((data[4] >> 9) & 0x3f) + 1980) * 10000) +
5000 ((data[4] >> 5) & 0xf) * 100 + (data[4] & 0x1F));
5001 count += scnprintf(serial_number + count, max - count, "%d",
5002 tmp);
5003
5004 count += scnprintf(serial_number + count, max - count, "%c%c",
5005 data[0] >> 8,
5006 data[0] & 0xFF);
5007
5008 count += scnprintf(serial_number + count, max - count, "%c%c%c",
5009 data[5] >> shift,
5010 data[6] >> shift,
5011 data[7] >> shift);
5012
5013 tmp = data[8];
5014 if (tmp >> 8 == 0)
5015 tmp = ('?' << 8) | (tmp & 0xFF);
5016 if ((tmp & 0xFF) == 0)
5017 tmp = (tmp & 0xFF00) | '?';
5018 count += scnprintf(serial_number + count, max - count, "%c%c",
5019 tmp >> 8,
5020 tmp & 0xFF);
5021
5022 cell_vendor = (shift == 8) ? (data[9] >> 8) : (data[9] & 0xFF);
5023 count += scnprintf(serial_number + count, max - count, "%c",
5024 cell_vendor);
5025
5026 if (shift == 8) {
5027 count += scnprintf(serial_number + count, max - count, "%02X",
5028 data[10] >> 8);
5029 } else {
5030 count += scnprintf(serial_number + count, max - count, "%c%c",
5031 data[10] >> 8, data[10] & 0xFF);
5032 }
5033
Jenny Ho1744cdd2021-03-12 15:41:18 +08005034 return count;
Ken Tsou8acade12020-07-09 03:17:35 +08005035}
5036
Ken Tsou8acade12020-07-09 03:17:35 +08005037static void *ct_seq_start(struct seq_file *s, loff_t *pos)
5038{
5039 struct max1720x_history *hi = (struct max1720x_history *)s->private;
5040
5041 if (*pos >= hi->history_count)
5042 return NULL;
5043 hi->history_index = *pos;
5044
5045 return &hi->history_index;
5046}
5047
5048static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
5049{
5050 loff_t *spos = (loff_t *)v;
5051 struct max1720x_history *hi = (struct max1720x_history *)s->private;
5052
5053 *pos = ++*spos;
5054 if (*pos >= hi->history_count)
5055 return NULL;
5056
5057 return spos;
5058}
5059
5060static void ct_seq_stop(struct seq_file *s, void *v)
5061{
5062 /* iterator in hi, no need to free */
5063}
5064
5065static int ct_seq_show(struct seq_file *s, void *v)
5066{
5067 char temp[96];
5068 loff_t *spos = (loff_t *)v;
5069 struct max1720x_history *hi = (struct max1720x_history *)s->private;
5070 const size_t offset = *spos * hi->page_size;
5071
5072 format_battery_history_entry(temp, sizeof(temp),
5073 hi->page_size, &hi->history[offset]);
5074 seq_printf(s, "%s\n", temp);
5075
5076 return 0;
5077}
5078
5079static const struct seq_operations ct_seq_ops = {
5080 .start = ct_seq_start,
5081 .next = ct_seq_next,
5082 .stop = ct_seq_stop,
5083 .show = ct_seq_show
5084};
5085
5086static int history_dev_open(struct inode *inode, struct file *file)
5087{
5088 struct max1720x_chip *chip =
5089 container_of(inode->i_cdev, struct max1720x_chip, hcdev);
5090 struct max1720x_history *hi;
5091 int history_count;
5092
5093 hi = __seq_open_private(file, &ct_seq_ops, sizeof(*hi));
5094 if (!hi)
5095 return -ENOMEM;
5096
5097 mutex_lock(&chip->history_lock);
5098 history_count = max1720x_history_read(chip, hi);
5099 if (history_count < 0) {
5100 mutex_unlock(&chip->history_lock);
5101 return history_count;
5102 } else if (history_count == 0) {
5103 dev_info(chip->dev, "No battery history has been recorded\n");
5104 }
5105 mutex_unlock(&chip->history_lock);
5106
5107 return 0;
5108}
5109
5110static int history_dev_release(struct inode *inode, struct file *file)
5111{
5112 struct max1720x_history *hi =
5113 ((struct seq_file *)file->private_data)->private;
5114
5115 if (hi) {
5116 max1720x_history_free(hi);
5117 seq_release_private(inode, file);
5118 }
5119
5120 return 0;
5121}
5122
5123static const struct file_operations hdev_fops = {
5124 .open = history_dev_open,
5125 .owner = THIS_MODULE,
5126 .read = seq_read,
5127 .release = history_dev_release,
5128};
5129
5130static void max1720x_cleanup_history(struct max1720x_chip *chip)
5131{
5132 if (chip->history_added)
5133 cdev_del(&chip->hcdev);
5134 if (chip->history_available)
5135 device_destroy(chip->hcclass, chip->hcmajor);
5136 if (chip->hcclass)
5137 class_destroy(chip->hcclass);
5138 if (chip->hcmajor != -1)
5139 unregister_chrdev_region(chip->hcmajor, 1);
5140}
5141
5142static int max1720x_init_history_device(struct max1720x_chip *chip)
5143{
5144 struct device *hcdev;
5145
5146 mutex_init(&chip->history_lock);
5147
5148 chip->hcmajor = -1;
5149
5150 /* cat /proc/devices */
5151 if (alloc_chrdev_region(&chip->hcmajor, 0, 1, HISTORY_DEVICENAME) < 0)
5152 goto no_history;
5153 /* ls /sys/class */
5154 chip->hcclass = class_create(THIS_MODULE, HISTORY_DEVICENAME);
5155 if (chip->hcclass == NULL)
5156 goto no_history;
5157 /* ls /dev/ */
5158 hcdev = device_create(chip->hcclass, NULL, chip->hcmajor, NULL,
5159 HISTORY_DEVICENAME);
5160 if (hcdev == NULL)
5161 goto no_history;
5162
5163 chip->history_available = true;
5164 cdev_init(&chip->hcdev, &hdev_fops);
5165 if (cdev_add(&chip->hcdev, chip->hcmajor, 1) == -1)
5166 goto no_history;
5167
5168 chip->history_added = true;
5169 return 0;
5170
5171no_history:
5172 max1720x_cleanup_history(chip);
5173 return -ENODEV;
5174}
5175
5176static int max1720x_init_history(struct max1720x_chip *chip)
5177{
5178 if (chip->gauge_type == MAX1730X_GAUGE_TYPE) {
5179 chip->nb_history_pages = MAX1730X_N_OF_HISTORY_PAGES;
5180 chip->history_page_size = MAX1730X_HISTORY_PAGE_SIZE;
5181 chip->nb_history_flag_reg = MAX1730X_N_OF_HISTORY_FLAGS_REG;
5182 } else if (chip->gauge_type == MAX1720X_GAUGE_TYPE) {
5183 chip->nb_history_pages = MAX1720X_N_OF_HISTORY_PAGES;
5184 chip->history_page_size = MAX1720X_HISTORY_PAGE_SIZE;
5185 chip->nb_history_flag_reg = MAX1720X_N_OF_HISTORY_FLAGS_REG;
5186 } else {
5187 return -EINVAL;
5188 }
5189
5190 return 0;
5191}
5192
AleX Pelosi3adb3372020-09-03 00:20:07 -07005193/* ------------------------------------------------------------------------- */
5194
Ken Tsou8acade12020-07-09 03:17:35 +08005195static int max17x0x_storage_info(gbms_tag_t tag, size_t *addr, size_t *count,
5196 void *ptr)
5197{
5198 struct max1720x_chip *chip = (struct max1720x_chip *)ptr;
5199
5200 if (!chip->history_available)
5201 return -ENOENT;
5202
5203 *count = chip->history_page_size * 2; /* storage is in byte */
5204 *addr = -1;
5205 return 0;
5206}
5207
Jenny Ho0f3bf2e2020-12-01 06:50:09 +08005208#define REG_HALF_HIGH(reg) ((reg >> 8) & 0x00FF)
5209#define REG_HALF_LOW(reg) (reg & 0x00FF)
5210static int max17x0x_collect_history_data(void *buff, size_t size,
5211 struct max1720x_chip *chip)
5212{
5213 struct max17x0x_eeprom_history hist = { 0 };
5214 u16 data, designcap;
5215
5216 if (REGMAP_READ(&chip->regmap, MAX1720X_TEMPCO, &data) == 0)
5217 hist.tempco = data;
5218
5219 if (REGMAP_READ(&chip->regmap, MAX1720X_RCOMP0, &data) == 0)
5220 hist.rcomp0 = data;
5221
5222 if (REGMAP_READ(&chip->regmap, MAX1720X_TIMERH, &data) == 0) {
5223 /* Convert LSB from 3.2hours(192min) to 5days(7200min) */
5224 hist.timerh = data * 192 / 7200;
5225 }
5226
5227 if (REGMAP_READ(&chip->regmap, MAX1720X_DESIGNCAP, &designcap) == 0) {
5228 /* multiply by 100 to convert from mAh to %, LSB 0.125% */
5229 if (REGMAP_READ(&chip->regmap, MAX1720X_FULLCAPNOM, &data) == 0)
5230 hist.fullcapnom = data * 800 / designcap;
5231 if (REGMAP_READ(&chip->regmap, MAX1720X_FULLCAPREP, &data) == 0)
5232 hist.fullcaprep = data * 800 / designcap;
5233 }
5234
5235 if (REGMAP_READ(&chip->regmap, MAX1720X_MIXSOC, &data) == 0) {
5236 /* Convert LSB from 1% to 2% */
5237 hist.mixsoc = REG_HALF_HIGH(data) / 2;
5238 }
5239
5240 if (REGMAP_READ(&chip->regmap, MAX1720X_VFSOC, &data) == 0) {
5241 /* Convert LSB from 1% to 2% */
5242 hist.vfsoc = REG_HALF_HIGH(data) / 2;
5243 }
5244
5245 if (REGMAP_READ(&chip->regmap, MAX1720X_MAXMINVOLT, &data) == 0) {
5246 /* LSB is 20mV, store values from 4.2V min */
5247 hist.maxvolt = (REG_HALF_HIGH(data) * 20 - 4200) / 20;
5248 /* Convert LSB from 20mV to 10mV, store values from 2.5V min */
5249 hist.minvolt = (REG_HALF_LOW(data) * 20 - 2500) / 10;
5250 }
5251
5252 if (REGMAP_READ(&chip->regmap, MAX1720X_MAXMINTEMP, &data) == 0) {
5253 /* Convert LSB from 1degC to 3degC, store values from 25degC min */
5254 hist.maxtemp = (REG_HALF_HIGH(data) - 25) / 3;
5255 /* Convert LSB from 1degC to 3degC, store values from -20degC min */
5256 hist.mintemp = (REG_HALF_LOW(data) + 20) / 3;
5257 }
5258
5259 if (REGMAP_READ(&chip->regmap, MAX1720X_MAXMINCURR, &data) == 0) {
5260 /* Convert LSB from 0.08A to 0.5A */
5261 hist.maxchgcurr = REG_HALF_HIGH(data) * 8 / 50;
5262 hist.maxdischgcurr = REG_HALF_LOW(data) * 8 / 50;
5263 }
5264
5265 memcpy(buff, &hist, sizeof(hist));
5266 return (size_t)sizeof(hist);
5267}
5268
Ken Tsou8acade12020-07-09 03:17:35 +08005269/*
5270 * The standard device call this with !data && !size && index=0 on start and
5271 * !data && !size && index<0 on stop. The call on start free and reload the
5272 * history from the gauge potentially increasing the number of entries (note
5273 * clients will not see that until they call start). On close the code just
5274 * release the allocated memory and entries: this is not a problem for cliets
5275 * that might be open because the data will be reloaded on next access.
5276 * This might create some churn but it's ok since we should not have more than
5277 * one client for this.
5278 */
5279static int max17x0x_storage_history_read(void *buff, size_t size, int index,
5280 struct max1720x_chip *chip)
5281{
5282 struct max1720x_history *hi = &chip->history_storage;
5283
5284 /* (!buff || !size) -> free the memory
5285 * if index == INVALID -> return 0
5286 * if index < 0 -> return -EIVAL
5287 * if index >= 0 -> re-read history
5288 */
5289 if (!buff || !size) {
5290 max1720x_history_free(hi);
5291 if (index == GBMS_STORAGE_INDEX_INVALID)
5292 return 0;
5293 }
5294
5295 if (index < 0)
5296 return -EINVAL;
5297
5298 /* read history if needed */
5299 if (hi->history_count < 0) {
5300 int ret;
5301
5302 ret = max1720x_history_read(chip, hi);
5303 if (ret < 0)
5304 return ret;
5305 }
5306
5307 /* index == 0 is ok here */
5308 if (index >= hi->history_count)
5309 return -ENODATA;
5310
5311 /* !buff, !size to read iterator count */
5312 if (!size || !buff)
5313 return hi->history_count;
5314
5315 memcpy(buff, &hi->history[index * chip->history_page_size], size);
5316 return size;
5317}
5318
5319static int max17x0x_storage_read_data(gbms_tag_t tag, void *buff, size_t size,
5320 int index, void *ptr)
5321{
5322 int ret;
5323 struct max1720x_chip *chip = (struct max1720x_chip *)ptr;
5324
5325 switch (tag) {
5326 case GBMS_TAG_HIST:
5327 /* short reads are invalid */
5328 if (size && size != chip->history_page_size * 2)
5329 return -EINVAL;
5330
5331 mutex_lock(&chip->history_lock);
5332 ret = max17x0x_storage_history_read(buff, size, index, chip);
5333 mutex_unlock(&chip->history_lock);
5334 return ret;
5335 default:
5336 ret = -ENOENT;
5337 break;
5338 }
5339
5340 return ret;
5341}
5342
AleX Pelosi3adb3372020-09-03 00:20:07 -07005343static int max17x0x_storage_iter(int index, gbms_tag_t *tag, void *ptr)
5344{
5345 struct max1720x_chip *chip = (struct max1720x_chip *)ptr;
5346 static gbms_tag_t keys[] = {GBMS_TAG_SNUM, GBMS_TAG_BCNT,
Jenny Ho36245b82021-04-13 16:14:41 +08005347 GBMS_TAG_MXSN, GBMS_TAG_MXCN,
AleX Pelosi9f326fb2020-10-27 01:50:47 -07005348 GBMS_TAG_RAVG, GBMS_TAG_RFCN,
5349 GBMS_TAG_CMPC, GBMS_TAG_DXAC};
AleX Pelosi3adb3372020-09-03 00:20:07 -07005350 const int count = ARRAY_SIZE(keys);
5351
5352
5353 if (index >= 0 && index < count) {
5354 *tag = keys[index];
5355 } else if (chip->history_available && index == count) {
5356 *tag = GBMS_TAG_HIST;
5357 } else {
5358 return -ENOENT;
5359 }
5360
5361 return 0;
5362}
5363
Ken Tsou8acade12020-07-09 03:17:35 +08005364static int max17x0x_storage_read(gbms_tag_t tag, void *buff, size_t size,
5365 void *ptr)
5366{
Ken Tsou8acade12020-07-09 03:17:35 +08005367 struct max1720x_chip *chip = (struct max1720x_chip *)ptr;
AleX Pelosi3adb3372020-09-03 00:20:07 -07005368 const struct max17x0x_reg *reg;
Jenny Ho094b6702021-04-14 16:10:28 +08005369 u16 data[32] = {0};
AleX Pelosi3adb3372020-09-03 00:20:07 -07005370 int ret;
Ken Tsou8acade12020-07-09 03:17:35 +08005371
5372 switch (tag) {
5373 case GBMS_TAG_SNUM:
Jenny Ho36245b82021-04-13 16:14:41 +08005374 case GBMS_TAG_MXSN:
Ken Tsou8acade12020-07-09 03:17:35 +08005375 reg = max17x0x_find_by_tag(&chip->regmap_nvram,
5376 MAX17X0X_TAG_SNUM);
5377 if (reg && reg->size > size)
5378 return -ERANGE;
Jenny Ho1744cdd2021-03-12 15:41:18 +08005379
Jenny Ho094b6702021-04-14 16:10:28 +08005380 ret = max17x0x_reg_load(&chip->regmap_nvram, reg, &data);
Jenny Ho1744cdd2021-03-12 15:41:18 +08005381 if (ret < 0)
5382 return ret;
5383
5384 if (chip->gauge_type == MAX1730X_GAUGE_TYPE)
Jenny Ho094b6702021-04-14 16:10:28 +08005385 ret = max1730x_decode_sn(buff, size, data);
Jenny Ho1744cdd2021-03-12 15:41:18 +08005386 else if (chip->gauge_type == MAX1720X_GAUGE_TYPE)
Jenny Ho094b6702021-04-14 16:10:28 +08005387 ret = max1720x_decode_sn(buff, size, data);
AleX Pelosi3adb3372020-09-03 00:20:07 -07005388 break;
5389
Ken Tsou8acade12020-07-09 03:17:35 +08005390 case GBMS_TAG_BCNT:
Jenny Ho36245b82021-04-13 16:14:41 +08005391 case GBMS_TAG_MXCN:
Ken Tsou8acade12020-07-09 03:17:35 +08005392 reg = max17x0x_find_by_tag(&chip->regmap_nvram,
5393 MAX17X0X_TAG_BCNT);
5394 if (reg && reg->size != size)
5395 return -ERANGE;
Jenny Ho1744cdd2021-03-12 15:41:18 +08005396 ret = max17x0x_reg_load(&chip->regmap_nvram, reg, buff);
5397 if (ret == 0)
5398 ret = reg->size;
AleX Pelosi3adb3372020-09-03 00:20:07 -07005399 break;
5400
AleX Pelosi43986542022-05-03 15:33:18 -07005401 /* RAVG: was POWER_SUPPLY_PROP_RESISTANCE_AVG, TODO: merge with EEPROM */
AleX Pelosi3adb3372020-09-03 00:20:07 -07005402 case GBMS_TAG_RAVG:
5403 if (size != sizeof(u16))
5404 return -ERANGE;
5405
5406 /* TODO(167639130) use tags */
5407 ret = batt_res_registers(chip, true, SEL_RES_AVG, (u16 *)buff);
5408 if (ret == -EINVAL)
5409 *(u16 *)buff = -1;
5410 return 0;
5411
AleX Pelosi43986542022-05-03 15:33:18 -07005412 /* RAVG: was POWER_SUPPLY_PROP_RES_FILTER_COUNT, TODO: merge with EEPROM */
AleX Pelosi3adb3372020-09-03 00:20:07 -07005413 case GBMS_TAG_RFCN:
5414 if (size != sizeof(u16))
5415 return -ERANGE;
5416
5417 /* TODO(167639130) use tags */
5418 ret = batt_res_registers(chip, true, SEL_RES_FILTER_COUNT,
5419 (u16 *)buff);
5420 if (ret == -EINVAL)
5421 *(u16 *)buff = -1;
5422 return 0;
5423
AleX Pelosi9f326fb2020-10-27 01:50:47 -07005424 case GBMS_TAG_DXAC:
5425/* MAX17201_DXACC_UPDATE_CNT = MAX1720X_NTALRTTH, */
5426 case GBMS_TAG_CMPC:
5427/* MAX17201_COMP_UPDATE_CNT = MAX1720X_NVALRTTH, */
5428 reg = NULL;
5429 break;
5430
Ken Tsou8acade12020-07-09 03:17:35 +08005431 default:
5432 reg = NULL;
5433 break;
5434 }
5435
5436 if (!reg)
5437 return -ENOENT;
5438
Ken Tsou8acade12020-07-09 03:17:35 +08005439 return ret;
5440}
5441
5442static int max17x0x_storage_write(gbms_tag_t tag, const void *buff, size_t size,
5443 void *ptr)
5444{
5445 int ret;
5446 const struct max17x0x_reg *reg;
5447 struct max1720x_chip *chip = (struct max1720x_chip *)ptr;
5448
5449 switch (tag) {
Jenny Ho36245b82021-04-13 16:14:41 +08005450 case GBMS_TAG_MXCN:
Ken Tsou8acade12020-07-09 03:17:35 +08005451 reg = max17x0x_find_by_tag(&chip->regmap_nvram,
5452 MAX17X0X_TAG_BCNT);
5453 if (reg && reg->size != size)
5454 return -ERANGE;
5455 break;
AleX Pelosi3adb3372020-09-03 00:20:07 -07005456
AleX Pelosi43986542022-05-03 15:33:18 -07005457 /* RAVG: Was POWER_SUPPLY_PROP_RESISTANCE_AVG, TODO: merge with EEPROM */
AleX Pelosi3adb3372020-09-03 00:20:07 -07005458 case GBMS_TAG_RAVG:
5459 if (size != sizeof(u16))
5460 return -ERANGE;
5461 return batt_res_registers(chip, false, SEL_RES_AVG,
5462 (u16 *)buff);
AleX Pelosi43986542022-05-03 15:33:18 -07005463 /* RAVG: Was POWER_SUPPLY_PROP_RES_FILTER_COUNT, TODO: merge with EEPROM */
AleX Pelosi3adb3372020-09-03 00:20:07 -07005464 case GBMS_TAG_RFCN:
5465 if (size != sizeof(u16))
5466 return -ERANGE;
5467 return batt_res_registers(chip, false, SEL_RES_FILTER_COUNT,
5468 (u16 *)buff);
5469
AleX Pelosi9f326fb2020-10-27 01:50:47 -07005470 case GBMS_TAG_DXAC:
5471/* MAX17201_DXACC_UPDATE_CNT = MAX1720X_NTALRTTH, */
5472 case GBMS_TAG_CMPC:
5473/* MAX17201_COMP_UPDATE_CNT = MAX1720X_NVALRTTH, */
5474 reg = NULL;
5475 break;
5476
Ken Tsou8acade12020-07-09 03:17:35 +08005477 default:
5478 reg = NULL;
5479 break;
5480 }
5481
5482 if (!reg)
5483 return -ENOENT;
5484
5485 ret = max17x0x_reg_store(&chip->regmap_nvram, reg, buff);
5486 if (ret == 0)
5487 ret = reg->size;
5488
5489 return ret;
5490}
5491
AleX Pelosi43986542022-05-03 15:33:18 -07005492/* when without eeprom */
Ken Tsou8acade12020-07-09 03:17:35 +08005493static struct gbms_storage_desc max17x0x_storage_dsc = {
5494 .info = max17x0x_storage_info,
5495 .iter = max17x0x_storage_iter,
5496 .read = max17x0x_storage_read,
5497 .write = max17x0x_storage_write,
5498 .read_data = max17x0x_storage_read_data,
5499};
5500
AleX Pelosi3adb3372020-09-03 00:20:07 -07005501/* ------------------------------------------------------------------------- */
5502
5503static int max17x0x_prop_iter(int index, gbms_tag_t *tag, void *ptr)
5504{
AleX Pelosi43986542022-05-03 15:33:18 -07005505 static gbms_tag_t keys[] = {GBMS_TAG_CLHI};
AleX Pelosi3adb3372020-09-03 00:20:07 -07005506 const int count = ARRAY_SIZE(keys);
5507
5508 if (index >= 0 && index < count) {
5509 *tag = keys[index];
5510 return 0;
5511 }
5512
5513 return -ENOENT;
5514}
5515
5516static int max17x0x_prop_read(gbms_tag_t tag, void *buff, size_t size,
5517 void *ptr)
5518{
5519 struct max1720x_chip *chip = (struct max1720x_chip *)ptr;
5520 int ret = -ENOENT;
AleX Pelosi3adb3372020-09-03 00:20:07 -07005521
5522 switch (tag) {
Jenny Ho0f3bf2e2020-12-01 06:50:09 +08005523 case GBMS_TAG_CLHI:
5524 ret = max17x0x_collect_history_data(buff, size, chip);
5525 break;
5526
AleX Pelosi3adb3372020-09-03 00:20:07 -07005527 default:
5528 break;
5529 }
5530
5531 return ret;
5532}
5533
5534static struct gbms_storage_desc max17x0x_prop_dsc = {
5535 .iter = max17x0x_prop_iter,
5536 .read = max17x0x_prop_read,
5537};
5538
5539/* ------------------------------------------------------------------------- */
5540
Ken Tsou8acade12020-07-09 03:17:35 +08005541/* this must be not blocking */
5542static void max17x0x_read_serial_number(struct max1720x_chip *chip)
5543{
Jenny Ho36245b82021-04-13 16:14:41 +08005544 struct device_node *node = chip->dev->of_node;
Ken Tsou8acade12020-07-09 03:17:35 +08005545 char buff[32] = {0};
Jenny Ho36245b82021-04-13 16:14:41 +08005546 u32 sn_source = EEPROM_SN;
Ken Tsou8acade12020-07-09 03:17:35 +08005547 int ret;
5548
Jenny Ho36245b82021-04-13 16:14:41 +08005549 ret = of_property_read_u32(node, "maxim,read-batt-sn", &sn_source);
5550 dev_info(chip->dev, "batt-sn source: %d (%d)\n", sn_source, ret);
5551
5552 if (sn_source == EEPROM_SN)
Jenny Ho1744cdd2021-03-12 15:41:18 +08005553 ret = gbms_storage_read(GBMS_TAG_MINF, buff, GBMS_MINF_LEN);
Jenny Ho36245b82021-04-13 16:14:41 +08005554 else if (sn_source == MAX1720X_SN)
5555 ret = gbms_storage_read(GBMS_TAG_MXSN, buff, sizeof(chip->serial_number));
Jenny Ho1744cdd2021-03-12 15:41:18 +08005556 else
5557 ret = gbms_storage_read(GBMS_TAG_SNUM, buff, sizeof(chip->serial_number));
Jenny Ho55836002020-11-06 14:41:18 +08005558
Jenny Ho1744cdd2021-03-12 15:41:18 +08005559 if (ret >= 0)
Ken Tsou8acade12020-07-09 03:17:35 +08005560 strncpy(chip->serial_number, buff, ret);
Jenny Ho1744cdd2021-03-12 15:41:18 +08005561 else
Ken Tsou8acade12020-07-09 03:17:35 +08005562 chip->serial_number[0] = '\0';
5563}
5564
5565static void max1720x_init_work(struct work_struct *work)
5566{
5567 struct max1720x_chip *chip = container_of(work, struct max1720x_chip,
5568 init_work.work);
5569 int ret = 0;
5570
5571 if (chip->gauge_type != -1) {
5572
AleX Pelosi9f326fb2020-10-27 01:50:47 -07005573 /* TODO: move to max1720x1 */
Ken Tsou8acade12020-07-09 03:17:35 +08005574 if (chip->regmap_nvram.regmap) {
5575 ret = gbms_storage_register(&max17x0x_storage_dsc,
Jenny Ho36245b82021-04-13 16:14:41 +08005576 "max1720x", chip);
Ken Tsou8acade12020-07-09 03:17:35 +08005577 if (ret == -EBUSY)
5578 ret = 0;
5579 }
5580
AleX Pelosi9f326fb2020-10-27 01:50:47 -07005581 /* these don't require nvm storage */
AleX Pelosi3adb3372020-09-03 00:20:07 -07005582 ret = gbms_storage_register(&max17x0x_prop_dsc, "maxfg", chip);
5583 if (ret == -EBUSY)
5584 ret = 0;
5585
Ken Tsou8acade12020-07-09 03:17:35 +08005586 if (ret == 0)
5587 ret = max1720x_init_chip(chip);
5588 if (ret == -EPROBE_DEFER) {
5589 schedule_delayed_work(&chip->init_work,
5590 msecs_to_jiffies(MAX1720X_DELAY_INIT_MS));
5591 return;
5592 }
5593 }
5594
5595 /* serial number might not be stored in the FG */
5596 max17x0x_read_serial_number(chip);
5597
5598 mutex_init(&chip->cap_estimate.batt_ce_lock);
5599 chip->prev_charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
5600 chip->fake_capacity = -EINVAL;
5601 chip->resume_complete = true;
5602 chip->init_complete = true;
Jack Wu94fd2c72022-03-29 20:44:19 +08005603 chip->bhi_acim = 0;
AleX Pelosi43986542022-05-03 15:33:18 -07005604
5605 max17x0x_init_sysfs(chip);
Ken Tsou8acade12020-07-09 03:17:35 +08005606
5607 /*
5608 * Handle any IRQ that might have been set before init
5609 * NOTE: will clear the POR bit and trigger model load if needed
5610 */
AleX Pelosiffcc7ec2020-09-08 17:05:01 -07005611 max1720x_fg_irq_thread_fn(-1, chip);
Ken Tsou8acade12020-07-09 03:17:35 +08005612
5613 dev_info(chip->dev, "init_work done\n");
5614 if (chip->gauge_type == -1)
5615 return;
5616
5617 /* Init History and Capacity Estimate only when gauge type is known. */
5618 ret = max1720x_init_history(chip);
5619 if (ret == 0)
5620 (void)max1720x_init_history_device(chip);
5621
5622 ret = batt_ce_load_data(&chip->regmap_nvram, &chip->cap_estimate);
5623 if (ret == 0)
5624 batt_ce_dump_data(&chip->cap_estimate, chip->ce_log);
5625}
5626
5627/* TODO: fix detection of 17301 for non samples looking at FW version too */
5628static int max17xxx_read_gauge_type(struct max1720x_chip *chip)
5629{
5630 u8 reg = MAX1720X_DEVNAME;
5631 struct i2c_msg xfer[2];
5632 uint8_t buf[2] = { };
5633 int ret, gauge_type;
5634
Ken Tsou8acade12020-07-09 03:17:35 +08005635 /* some maxim IF-PMIC corrupt reads w/o Rs b/152373060 */
5636 xfer[0].addr = chip->primary->addr;
5637 xfer[0].flags = 0;
5638 xfer[0].len = 1;
5639 xfer[0].buf = &reg;
5640
5641 xfer[1].addr = chip->primary->addr;
5642 xfer[1].flags = I2C_M_RD;
5643 xfer[1].len = 2;
5644 xfer[1].buf = buf;
5645
5646 ret = i2c_transfer(chip->primary->adapter, xfer, 2);
5647 if (ret != 2)
5648 return -EIO;
5649
AleX Pelosi962aedf2021-01-07 15:39:43 -08005650 /* it might need devname later */
Ken Tsou8acade12020-07-09 03:17:35 +08005651 chip->devname = buf[1] << 8 | buf[0];
Jenny Hod5def242021-04-28 10:51:58 +08005652 dev_info(chip->dev, "chip devname:0x%X\n", chip->devname);
AleX Pelosi962aedf2021-01-07 15:39:43 -08005653
5654 ret = of_property_read_u32(chip->dev->of_node, "maxim,gauge-type",
5655 &gauge_type);
5656 if (ret == 0) {
5657 dev_warn(chip->dev, "forced gauge type to %d\n", gauge_type);
5658 return gauge_type;
5659 }
5660
5661 /* 0 not M5, !=0 M5 */
5662 ret = max_m5_check_devname(chip->devname);
5663 if (ret)
5664 return MAX_M5_GAUGE_TYPE;
Ken Tsou8acade12020-07-09 03:17:35 +08005665
5666 switch (chip->devname >> 4) {
5667 case 0x404: /* max1730x sample */
5668 case 0x405: /* max1730x pass2 silicon initial samples */
5669 case 0x406: /* max1730x pass2 silicon */
5670 gauge_type = MAX1730X_GAUGE_TYPE;
5671 break;
Jenny Hod5def242021-04-28 10:51:58 +08005672 default:
Jenny Hod52e05d2021-04-12 17:16:20 +08005673 break;
Jenny Hod5def242021-04-28 10:51:58 +08005674 }
5675
5676 switch (chip->devname & 0x000F) {
5677 case 0x1: /* max17201 or max17211 */
5678 case 0x5: /* max17205 or max17215 */
AleX Pelosi962aedf2021-01-07 15:39:43 -08005679 default:
Ken Tsou8acade12020-07-09 03:17:35 +08005680 gauge_type = MAX1720X_GAUGE_TYPE;
5681 break;
5682 }
5683
5684 return gauge_type;
5685}
5686
5687
5688/* NOTE: NEED TO COME BEFORE REGISTER ACCESS */
5689static int max17x0x_regmap_init(struct max1720x_chip *chip)
5690{
5691 int secondary_address = 0xb;
5692 struct device *dev = chip->dev;
5693
5694 if (chip->gauge_type == MAX1730X_GAUGE_TYPE) {
5695 /* redefine primary for max1730x */
5696 chip->regmap.regmap = devm_regmap_init_i2c(chip->primary,
5697 &max1730x_regmap_cfg);
5698 if (IS_ERR(chip->regmap.regmap)) {
AleX Pelosi78a4bea2020-09-01 19:02:24 -07005699 dev_err(chip->dev, "Failed to re-initialize regmap (%ld)\n",
Ken Tsou8acade12020-07-09 03:17:35 +08005700 IS_ERR_VALUE(chip->regmap.regmap));
5701 return -EINVAL;
5702 }
5703
5704 /* shadow override is not supported on early samples */
5705 chip->shadow_override = (chip->devname >> 4) != 0x404;
5706
5707 chip->regmap.regtags.max = ARRAY_SIZE(max1730x);
5708 chip->regmap.regtags.map = max1730x;
5709 chip->fixups_fn = max1730x_fixups;
5710 } else if (chip->gauge_type == MAX_M5_GAUGE_TYPE) {
5711 int ret;
5712
5713 ret = max_m5_regmap_init(&chip->regmap, chip->primary);
5714 if (ret < 0) {
AleX Pelosi78a4bea2020-09-01 19:02:24 -07005715 dev_err(chip->dev, "Failed to re-initialize regmap (%ld)\n",
Ken Tsou8acade12020-07-09 03:17:35 +08005716 IS_ERR_VALUE(chip->regmap.regmap));
5717 return -EINVAL;
5718 }
5719
5720 chip->shadow_override = false;
5721 secondary_address = 0;
5722 } else if (chip->gauge_type == MAX1720X_GAUGE_TYPE) {
5723
5724 chip->regmap.regmap = devm_regmap_init_i2c(chip->primary,
5725 &max1720x_regmap_cfg);
5726 if (IS_ERR(chip->regmap.regmap)) {
AleX Pelosi78a4bea2020-09-01 19:02:24 -07005727 dev_err(chip->dev, "Failed to initialize primary regmap (%ld)\n",
Ken Tsou8acade12020-07-09 03:17:35 +08005728 IS_ERR_VALUE(chip->regmap.regmap));
5729 return -EINVAL;
5730 }
5731
5732 /* max1720x is default map */
5733 chip->regmap.regtags.max = ARRAY_SIZE(max1720x);
5734 chip->regmap.regtags.map = max1720x;
5735 }
5736
5737 /* todo read secondary address from DT */
5738 if (!secondary_address) {
5739 dev_warn(chip->dev, "Device 0x%x has no permanent storage\n",
5740 chip->devname);
5741 return 0;
5742 }
5743
Ken Tsou98b71642020-07-09 16:17:29 +08005744 chip->secondary = i2c_new_ancillary_device(chip->primary,
Ken Tsou8acade12020-07-09 03:17:35 +08005745 "nvram",
5746 secondary_address);
5747 if (chip->secondary == NULL) {
5748 dev_err(dev, "Failed to initialize secondary i2c device\n");
5749 return -ENODEV;
5750 }
5751
5752 i2c_set_clientdata(chip->secondary, chip);
5753
5754 if (chip->gauge_type == MAX1730X_GAUGE_TYPE) {
5755 chip->regmap_nvram.regmap =
5756 devm_regmap_init_i2c(chip->secondary,
5757 &max1730x_regmap_nvram_cfg);
5758 if (IS_ERR(chip->regmap_nvram.regmap)) {
AleX Pelosi5077fc52020-09-10 21:44:48 -07005759 dev_err(chip->dev, "Failed to initialize nvram regmap (%ld)\n",
5760 PTR_ERR(chip->regmap_nvram.regmap));
Ken Tsou8acade12020-07-09 03:17:35 +08005761 return -EINVAL;
5762 }
5763
5764 chip->regmap_nvram.regtags.max = ARRAY_SIZE(max1730x);
5765 chip->regmap_nvram.regtags.map = max1730x;
5766 } else {
5767 chip->regmap_nvram.regmap =
5768 devm_regmap_init_i2c(chip->secondary,
5769 &max1720x_regmap_nvram_cfg);
5770 if (IS_ERR(chip->regmap_nvram.regmap)) {
AleX Pelosi5077fc52020-09-10 21:44:48 -07005771 dev_err(chip->dev, "Failed to initialize nvram regmap (%ld)\n",
5772 PTR_ERR(chip->regmap_nvram.regmap));
Ken Tsou8acade12020-07-09 03:17:35 +08005773 return -EINVAL;
5774 }
5775
5776 chip->regmap_nvram.regtags.max = ARRAY_SIZE(max1720x);
5777 chip->regmap_nvram.regtags.map = max1720x;
5778 }
5779
5780 return 0;
5781}
5782
5783static int max1720x_init_irq(struct max1720x_chip *chip)
5784{
5785 unsigned long irqf = IRQF_TRIGGER_LOW | IRQF_ONESHOT;
5786 int ret, irqno;
5787
5788 chip->irq_shared = of_property_read_bool(chip->dev->of_node,
5789 "maxim,irqf-shared");
5790 irqno = chip->primary->irq;
5791 if (!irqno) {
5792 int irq_gpio;
5793
5794 irq_gpio = of_get_named_gpio(chip->dev->of_node,
5795 "maxim,irq-gpio", 0);
5796 if (irq_gpio >= 0) {
5797 chip->primary->irq = gpio_to_irq(irq_gpio);
5798 if (chip->primary->irq <= 0) {
5799 chip->primary->irq = 0;
5800 dev_warn(chip->dev, "fg irq not avalaible\n");
5801 return 0;
5802 }
5803 }
5804 }
5805
5806 if (chip->irq_shared)
5807 irqf |= IRQF_SHARED;
5808
5809 ret = request_threaded_irq(chip->primary->irq, NULL,
5810 max1720x_fg_irq_thread_fn, irqf,
5811 MAX1720X_I2C_DRIVER_NAME, chip);
5812 dev_info(chip->dev, "FG irq handler registered at %d (%d)\n",
5813 chip->primary->irq, ret);
5814 if (ret == 0)
5815 enable_irq_wake(chip->primary->irq);
5816
5817 return ret;
5818}
5819
AleX Pelosidc8e6042020-09-21 15:48:29 -07005820/* possible race */
Ken Tsou8acade12020-07-09 03:17:35 +08005821void *max1720x_get_model_data(struct i2c_client *client)
5822{
5823 struct max1720x_chip *chip = i2c_get_clientdata(client);
AleX Pelosidc8e6042020-09-21 15:48:29 -07005824
5825 return chip ? chip->model_data : NULL;
Ken Tsou8acade12020-07-09 03:17:35 +08005826}
Ken Tsou8acade12020-07-09 03:17:35 +08005827
5828static int max1720x_probe(struct i2c_client *client,
5829 const struct i2c_device_id *id)
5830{
5831 struct max1720x_chip *chip;
5832 struct device *dev = &client->dev;
5833 struct power_supply_config psy_cfg = { };
5834 const struct max17x0x_reg *reg;
Jenny Ho36b6c9f2020-12-21 09:57:16 +08005835 const char *psy_name = NULL;
Jenny Ho5381a6f2021-08-11 14:34:45 +08005836 char monitor_name[32];
Ken Tsou8acade12020-07-09 03:17:35 +08005837 int ret = 0;
5838
5839 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
5840 if (!chip)
5841 return -ENOMEM;
5842
5843 chip->dev = dev;
Jack Wue3ccc812022-08-30 23:04:57 +08005844 chip->fake_battery = of_property_read_bool(dev->of_node, "maxim,no-battery") ? 0 : -1;
Ken Tsou8acade12020-07-09 03:17:35 +08005845 chip->primary = client;
5846 chip->batt_id_defer_cnt = DEFAULT_BATTERY_ID_RETRIES;
5847 i2c_set_clientdata(client, chip);
5848
5849 /* NOTE: < 0 not avalable, it could be a bare MLB */
5850 chip->gauge_type = max17xxx_read_gauge_type(chip);
5851 if (chip->gauge_type < 0)
5852 chip->gauge_type = -1;
5853
5854 /* needs chip->primary and (optional) chip->secondary */
5855 ret = max17x0x_regmap_init(chip);
5856 if (ret < 0) {
5857 dev_err(dev, "Failed to initialize regmap(s)\n");
5858 goto i2c_unregister;
5859 }
5860
5861 dev_warn(chip->dev, "device gauge_type: %d shadow_override=%d\n",
5862 chip->gauge_type, chip->shadow_override);
5863
5864 if (of_property_read_bool(dev->of_node, "maxim,log_writes")) {
5865 bool debug_reglog;
5866
5867 debug_reglog = max17x0x_reglog_init(chip);
5868 dev_info(dev, "write log %savailable\n",
5869 debug_reglog ? "" : "not ");
5870 }
5871
5872 /* M5 requires zero IRQ */
5873 chip->zero_irq = -1;
5874 if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
5875 chip->zero_irq = 1;
5876 if (chip->zero_irq == -1)
5877 chip->zero_irq = of_property_read_bool(chip->dev->of_node,
5878 "maxim,zero-irq");
5879
5880 /* TODO: do not request the interrupt if the gauge is not present */
5881 ret = max1720x_init_irq(chip);
5882 if (ret < 0) {
5883 dev_err(dev, "cannot allocate irq\n");
5884 return ret;
5885 }
5886
Ken Tsou8acade12020-07-09 03:17:35 +08005887 psy_cfg.drv_data = chip;
5888 psy_cfg.of_node = chip->dev->of_node;
Jenny Ho36b6c9f2020-12-21 09:57:16 +08005889
5890 ret = of_property_read_string(dev->of_node,
5891 "maxim,dual-battery", &psy_name);
5892 if (ret == 0)
5893 chip->max1720x_psy_desc.name = devm_kstrdup(dev, psy_name, GFP_KERNEL);
5894 else
5895 chip->max1720x_psy_desc.name = "maxfg";
5896
Jenny Hoa1e85e92022-05-16 13:36:05 +08005897 dev_info(dev, "max1720x_psy_desc.name=%s\n", chip->max1720x_psy_desc.name);
Jenny Ho36b6c9f2020-12-21 09:57:16 +08005898
Thierry Strudel4ab0fcb2021-02-02 10:31:46 -08005899 chip->max1720x_psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
5900 chip->max1720x_psy_desc.get_property = max1720x_get_property;
5901 chip->max1720x_psy_desc.set_property = max1720x_set_property;
5902 chip->max1720x_psy_desc.property_is_writeable = max1720x_property_is_writeable;
5903 chip->max1720x_psy_desc.properties = max1720x_battery_props;
5904 chip->max1720x_psy_desc.num_properties = ARRAY_SIZE(max1720x_battery_props);
5905
5906 if (of_property_read_bool(dev->of_node, "maxim,psy-type-unknown"))
5907 chip->max1720x_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
Jenny Ho36b6c9f2020-12-21 09:57:16 +08005908
5909 chip->psy = devm_power_supply_register(dev, &chip->max1720x_psy_desc,
Ken Tsou8acade12020-07-09 03:17:35 +08005910 &psy_cfg);
5911 if (IS_ERR(chip->psy)) {
5912 dev_err(dev, "Couldn't register as power supply\n");
5913 ret = PTR_ERR(chip->psy);
5914 goto irq_unregister;
5915 }
5916
5917 ret = device_create_file(&chip->psy->dev, &dev_attr_offmode_charger);
5918 if (ret) {
5919 dev_err(dev, "Failed to create offmode_charger attribute\n");
5920 goto psy_unregister;
5921 }
5922
AleX Pelosi3adb3372020-09-03 00:20:07 -07005923 /* Was POWER_SUPPLY_PROP_RESISTANCE_ID */
5924 ret = device_create_file(&chip->psy->dev, &dev_attr_resistance_id);
5925 if (ret)
5926 dev_err(dev, "Failed to create resistance_id attribute\n");
5927
5928 /* POWER_SUPPLY_PROP_RESISTANCE */
5929 ret = device_create_file(&chip->psy->dev, &dev_attr_resistance);
5930 if (ret)
5931 dev_err(dev, "Failed to create resistance attribute\n");
5932
Jenny Hoc6bc5882021-02-18 09:21:21 +08005933 /* Read GMSR */
5934 ret = device_create_file(&chip->psy->dev, &dev_attr_gmsr);
5935 if (ret)
5936 dev_err(dev, "Failed to create gmsr attribute\n");
5937
Jenny Ho39b2def2022-03-02 18:18:13 +08005938 /* RC switch enable/disable */
5939 ret = device_create_file(&chip->psy->dev, &dev_attr_rc_switch_enable);
5940 if (ret)
5941 dev_err(dev, "Failed to create rc_switch_enable attribute\n");
5942
AleX Pelosi3adb3372020-09-03 00:20:07 -07005943 /*
5944 * TODO:
5945 * POWER_SUPPLY_PROP_CHARGE_FULL_ESTIMATE -> GBMS_TAG_GCFE
5946 * POWER_SUPPLY_PROP_RES_FILTER_COUNT -> GBMS_TAG_RFCN
AleX Pelosi3adb3372020-09-03 00:20:07 -07005947 */
5948
Ken Tsou8acade12020-07-09 03:17:35 +08005949 /* M5 battery model needs batt_id and is setup during init() */
5950 chip->model_reload = MAX_M5_LOAD_MODEL_DISABLED;
5951 if (chip->gauge_type == MAX_M5_GAUGE_TYPE) {
5952 ret = device_create_file(&chip->psy->dev,
5953 &dev_attr_m5_model_state);
5954 if (ret)
5955 dev_err(dev, "Failed to create model_state, ret=%d\n",
5956 ret);
5957 }
5958
Jenny Ho36b6c9f2020-12-21 09:57:16 +08005959 chip->ce_log = logbuffer_register(chip->max1720x_psy_desc.name);
Ken Tsou8acade12020-07-09 03:17:35 +08005960 if (IS_ERR(chip->ce_log)) {
5961 ret = PTR_ERR(chip->ce_log);
5962 dev_err(dev, "failed to obtain logbuffer, ret=%d\n", ret);
5963 chip->ce_log = NULL;
5964 }
5965
Jenny Ho5381a6f2021-08-11 14:34:45 +08005966 scnprintf(monitor_name, sizeof(monitor_name), "%s_%s",
5967 chip->max1720x_psy_desc.name, "monitor");
5968 chip->monitor_log = logbuffer_register(monitor_name);
5969 if (IS_ERR(chip->monitor_log)) {
5970 ret = PTR_ERR(chip->monitor_log);
5971 dev_err(dev, "failed to obtain logbuffer, ret=%d\n", ret);
5972 chip->monitor_log = NULL;
5973 }
5974
AleX Pelosi9e8633f2022-05-06 18:21:12 +00005975 ret = of_property_read_u32(dev->of_node, "google,bhi-fcn-count",
5976 &chip->bhi_fcn_count);
5977 if (ret < 0)
5978 chip->bhi_fcn_count = BHI_CAP_FCN_COUNT;
5979
Ken Tsou8acade12020-07-09 03:17:35 +08005980 /* use VFSOC until it can confirm that FG Model is running */
5981 reg = max17x0x_find_by_tag(&chip->regmap, MAX17X0X_TAG_vfsoc);
5982 chip->reg_prop_capacity_raw = (reg) ? reg->reg : MAX1720X_REPSOC;
5983
5984 INIT_DELAYED_WORK(&chip->cap_estimate.settle_timer,
5985 batt_ce_capacityfiltered_work);
5986 INIT_DELAYED_WORK(&chip->init_work, max1720x_init_work);
5987 INIT_DELAYED_WORK(&chip->model_work, max1720x_model_work);
Jenny Ho39b2def2022-03-02 18:18:13 +08005988 INIT_DELAYED_WORK(&chip->rc_switch.switch_work, max1720x_rc_work);
Ken Tsou8acade12020-07-09 03:17:35 +08005989
5990 schedule_delayed_work(&chip->init_work, 0);
5991
5992 return 0;
5993
5994psy_unregister:
5995 power_supply_unregister(chip->psy);
5996irq_unregister:
5997 free_irq(chip->primary->irq, chip);
5998i2c_unregister:
5999 i2c_unregister_device(chip->secondary);
6000
6001 return ret;
6002}
6003
6004static int max1720x_remove(struct i2c_client *client)
6005{
6006 struct max1720x_chip *chip = i2c_get_clientdata(client);
6007
6008 if (chip->ce_log) {
AleX Pelosid71f5852020-08-26 18:40:28 -07006009 logbuffer_unregister(chip->ce_log);
Ken Tsou8acade12020-07-09 03:17:35 +08006010 chip->ce_log = NULL;
6011 }
6012
6013 max1720x_cleanup_history(chip);
6014 max_m5_free_data(chip->model_data);
6015 cancel_delayed_work(&chip->init_work);
6016 cancel_delayed_work(&chip->model_work);
Jenny Ho39b2def2022-03-02 18:18:13 +08006017 cancel_delayed_work(&chip->rc_switch.switch_work);
Ken Tsou8acade12020-07-09 03:17:35 +08006018
6019 if (chip->primary->irq)
6020 free_irq(chip->primary->irq, chip);
6021 power_supply_unregister(chip->psy);
6022
6023 if (chip->secondary)
6024 i2c_unregister_device(chip->secondary);
6025
6026 return 0;
6027}
6028
6029static const struct of_device_id max1720x_of_match[] = {
6030 { .compatible = "maxim,max1720x"},
6031 { .compatible = "maxim,max77729f"},
6032 { .compatible = "maxim,max77759"},
6033 {},
6034};
6035MODULE_DEVICE_TABLE(of, max1720x_of_match);
6036
6037static const struct i2c_device_id max1720x_id[] = {
6038 {"max1720x", 0},
6039 {}
6040};
6041MODULE_DEVICE_TABLE(i2c, max1720x_id);
6042
6043#ifdef CONFIG_PM_SLEEP
6044static int max1720x_pm_suspend(struct device *dev)
6045{
6046 struct i2c_client *client = to_i2c_client(dev);
6047 struct max1720x_chip *chip = i2c_get_clientdata(client);
6048
6049 pm_runtime_get_sync(chip->dev);
6050 chip->resume_complete = false;
6051 pm_runtime_put_sync(chip->dev);
6052
6053 return 0;
6054}
6055
6056static int max1720x_pm_resume(struct device *dev)
6057{
6058 struct i2c_client *client = to_i2c_client(dev);
6059 struct max1720x_chip *chip = i2c_get_clientdata(client);
6060
6061 pm_runtime_get_sync(chip->dev);
6062 chip->resume_complete = true;
Wasb Liudc49a932022-03-01 14:44:17 +08006063 if (chip->irq_disabled) {
6064 enable_irq(chip->primary->irq);
6065 chip->irq_disabled = false;
6066 }
Ken Tsou8acade12020-07-09 03:17:35 +08006067 pm_runtime_put_sync(chip->dev);
6068
6069 return 0;
6070}
6071#endif
6072
6073static const struct dev_pm_ops max1720x_pm_ops = {
Jenny Ho6594dc92021-03-31 14:44:36 +08006074 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(max1720x_pm_suspend, max1720x_pm_resume)
Ken Tsou8acade12020-07-09 03:17:35 +08006075};
6076
6077static struct i2c_driver max1720x_i2c_driver = {
6078 .driver = {
6079 .name = "max1720x",
6080 .of_match_table = max1720x_of_match,
6081 .pm = &max1720x_pm_ops,
6082 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
6083 },
6084 .id_table = max1720x_id,
6085 .probe = max1720x_probe,
6086 .remove = max1720x_remove,
6087};
6088
6089module_i2c_driver(max1720x_i2c_driver);
6090MODULE_AUTHOR("Thierry Strudel <tstrudel@google.com>");
6091MODULE_AUTHOR("AleX Pelosi <apelosi@google.com>");
6092MODULE_DESCRIPTION("MAX17x01/MAX17x05 Fuel Gauge");
6093MODULE_LICENSE("GPL");