blob: 3edc348484c22870ededdc29421aa9b15aad154f [file] [log] [blame]
AleX Pelosi78a4bea2020-09-01 19:02:24 -07001/* SPDX-License-Identifier: GPL-2.0 */
Ken Tsou8acade12020-07-09 03:17:35 +08002/*
AleX Pelosi78a4bea2020-09-01 19:02:24 -07003 * Copyright 2019 Google, LLC
Ken Tsou8acade12020-07-09 03:17:35 +08004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#ifndef MAX_M5_H_
17#define MAX_M5_H_
18
19#include "max1720x_battery.h"
Jenny Hoc6bc5882021-02-18 09:21:21 +080020#include "max_m5_reg.h"
Ken Tsou8acade12020-07-09 03:17:35 +080021
22#define MAX_M5_I2C_ADDR 0x6C
23
Ken Tsou8acade12020-07-09 03:17:35 +080024
25/* change to 1 or 0 to load FG model with default parameters on startup */
26#define MAX_M5_LOAD_MODEL_DISABLED -1
27#define MAX_M5_LOAD_MODEL_IDLE 0
Jenny Hoba588612023-11-29 17:59:58 +080028#define MAX_M5_LOAD_MODEL_REQUEST 1
Ken Tsou8acade12020-07-09 03:17:35 +080029
30#define MAX_M5_FG_MODEL_START 0x80
31#define MAX_M5_FG_MODEL_SIZE 48
32
33#define MAX_M5_UNLOCK_EXTRA_CONFIG 0x60
34#define MAX_M5_UNLOCK_EXTRA_CONFIG_UNLOCK_CODE 0x80
35#define MAX_M5_UNLOCK_EXTRA_CONFIG_LOCK_CODE 0x00
36
37#define MAX_M5_UNLOCK_MODEL_ACCESS 0x62
38#define MAX_M5_MODEL_ACCESS_UNLOCK_CODE 0xc459
39#define MAX_M5_MODEL_ACCESS_LOCK_CODE 0x0000
40#define MAX_M5_MODEL_ACCESS_LOCK_OK 0xFFFF
41
42#define MAX_M5_TCURVE 0xB9
Jenny Hob5e49d62024-03-27 22:29:27 +080043#define MAX_M5_VFOCV 0xFB
Ken Tsou8acade12020-07-09 03:17:35 +080044#define MAX_M5_VFSOC 0xFF
45
Jenny Ho6a74c7a2023-03-16 05:47:15 +080046#define MAX_M5_COMMAND 0x60
47#define MAX_M5_COMMAND_HARDWARE_RESET 0x000F
48
AleX Pelosi962aedf2021-01-07 15:39:43 -080049/* model version */
50#define MAX_M5_INVALID_VERSION -1
51
Jenny Ho6a74c7a2023-03-16 05:47:15 +080052#define MAX_M5_RECAL_MAX_ROUNDS 3
53
Jenny Ho2154dcc2023-07-27 07:52:04 +080054#define MAX_M5_RETRY_TIMES 3
AleX Pelosi962aedf2021-01-07 15:39:43 -080055
Jenny Ho8c1268f2023-12-23 03:00:05 +080056#define MAX_M5_COTRIM 0xEB
57
Ken Tsou8acade12020-07-09 03:17:35 +080058/** ------------------------------------------------------------------------ */
59
60/*
AleX Pelosi76b63502020-11-03 16:49:44 -080061 * Custom parameters are updated while the device is runnig.
62 * NOTE: a subset (model_state_save) is saved to permanent storage every "n"
63 * cycles and restored when the model is reloaded (usually on POR).
64 * TODO: handle switching between RC1 and RC2 model types.
Ken Tsou8acade12020-07-09 03:17:35 +080065 */
66struct max_m5_custom_parameters {
67 u16 iavg_empty; /* WV */
68 u16 relaxcfg;
69 u16 learncfg;
70 u16 config;
71 u16 config2;
72 u16 fullsocthr;
73 u16 fullcaprep; /* WV */
74 u16 designcap;
75 u16 dpacc; /* WV */
76 u16 dqacc; /* WV */
77 u16 fullcapnom; /* WV */
78 u16 v_empty;
79 u16 qresidual00; /* WV */
80 u16 qresidual10; /* WV */
81 u16 qresidual20; /* WV */
82 u16 qresidual30; /* WV */
83 u16 rcomp0; /* WV */
84 u16 tempco; /* WV */
85 u16 ichgterm;
86 u16 tgain;
87 u16 toff;
88 u16 tcurve; /* write to 0x00B9 */
89 u16 misccfg; /* 0x9d0 for internal current sense, 0x8d0 external */
90
91 u16 atrate;
92 u16 convgcfg;
93 u16 filtercfg; /* write to 0x0029 */
AleX Pelosi962aedf2021-01-07 15:39:43 -080094 u16 taskperiod;
Jenny Hoe8b877c2022-01-10 03:27:53 +080095 u16 cgain;
Ken Tsou8acade12020-07-09 03:17:35 +080096} __attribute__((packed));
97
AleX Pelosi76b63502020-11-03 16:49:44 -080098/* this is what is saved and restored to/from GMSR */
Ken Tsou8acade12020-07-09 03:17:35 +080099struct model_state_save {
100 u16 rcomp0;
101 u16 tempco;
102 u16 fullcaprep;
103 u16 cycles;
104 u16 fullcapnom;
105 u16 qresidual00;
106 u16 qresidual10;
107 u16 qresidual20;
108 u16 qresidual30;
Jenny Hodc6c8a02021-10-29 06:14:33 +0800109 u16 cv_mixcap;
Ken Tsou8acade12020-07-09 03:17:35 +0800110 u16 halftime;
Jenny Hof77200e2021-05-31 17:32:55 +0800111 u8 crc;
AleX Pelosi76b63502020-11-03 16:49:44 -0800112} __attribute__((packed));
Ken Tsou8acade12020-07-09 03:17:35 +0800113
Jenny Ho6a74c7a2023-03-16 05:47:15 +0800114struct max_m5_recalibration_data {
115 int state;
116 int rounds;
117 int base_cycle_reg;
118 u16 target_cap;
119 struct mutex lock;
120};
121
Ken Tsou8acade12020-07-09 03:17:35 +0800122struct max_m5_data {
123 struct device *dev;
AleX Pelosi76b63502020-11-03 16:49:44 -0800124 struct max17x0x_regmap *regmap;
AleX Pelosi962aedf2021-01-07 15:39:43 -0800125 int cap_lsb; /* b/177099997 */
Ken Tsou8acade12020-07-09 03:17:35 +0800126
AleX Pelosi76b63502020-11-03 16:49:44 -0800127 /* initial parameters are in device tree they are also learned */
Ken Tsou8acade12020-07-09 03:17:35 +0800128 struct max_m5_custom_parameters parameters;
129 u16 cycles;
Jenny Hodc6c8a02021-10-29 06:14:33 +0800130 u16 cv_mixcap;
Ken Tsou8acade12020-07-09 03:17:35 +0800131 u16 halftime;
132
Ken Tsou8acade12020-07-09 03:17:35 +0800133 int custom_model_size;
134 u16 *custom_model;
AleX Pelosi962aedf2021-01-07 15:39:43 -0800135 u32 model_version;
Jenny Ho7c691da2021-05-19 06:15:54 +0800136 bool force_reset_model_data;
Jenny Ho2154dcc2023-07-27 07:52:04 +0800137 int load_retry;
Ken Tsou8acade12020-07-09 03:17:35 +0800138
AleX Pelosi76b63502020-11-03 16:49:44 -0800139 /* to/from GMSR */
Ken Tsou8acade12020-07-09 03:17:35 +0800140 struct model_state_save model_save;
Jenny Ho6a74c7a2023-03-16 05:47:15 +0800141
142 /* recalibration */
143 struct max_m5_recalibration_data recal;
144};
145
146enum max_m5_re_cal_state {
147 RE_CAL_STATE_IDLE = 0,
148 RE_CAL_STATE_FG_RESET = 1,
149 RE_CAL_STATE_LEARNING = 2,
150};
151
152enum max_m5_re_cal_algo {
153 RE_CAL_ALGO_0 = 0,
154 RE_CAL_ALGO_1 = 1,
Ken Tsou8acade12020-07-09 03:17:35 +0800155};
156
AleX Pelosi32892282020-09-11 02:29:20 -0700157/** ------------------------------------------------------------------------ */
158
AleX Pelosi962aedf2021-01-07 15:39:43 -0800159int max_m5_model_read_version(const struct max_m5_data *m5_data);
Spade Lee5c3e6202024-03-29 08:22:59 +0000160int max_m5_model_write_version(const struct max_m5_data *m5_data, int version);
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800161int max_m5_model_get_cap_lsb(const struct max_m5_data *m5_data);
Jenny Hoc6bc5882021-02-18 09:21:21 +0800162int max_m5_reset_state_data(struct max_m5_data *m5_data);
163int max_m5_needs_reset_model_data(const struct max_m5_data *m5_data);
Jenny Ho6a74c7a2023-03-16 05:47:15 +0800164int max_m5_recal_state(const struct max_m5_data *m5_data);
165int max_m5_recal_cycle(const struct max_m5_data *m5_data);
166int max_m5_recalibration(struct max_m5_data *m5_data, int algo, u16 cap);
167int max_m5_check_recal_state(struct max_m5_data *m5_data, int algo, u16 eeprom_cycle);
168int m5_init_custom_parameters(struct device *dev, struct max_m5_data *m5_data,
169 struct device_node *node);
Jenny Ho89230272023-09-01 18:16:58 +0800170int max_m5_get_designcap(const struct max_m5_data *m5_data);
Jenny Hoa805e0f2023-12-20 17:05:59 +0800171int max_m5_model_lock(struct regmap *regmap, bool enabled);
AleX Pelosi962aedf2021-01-07 15:39:43 -0800172
173/*
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800174 * max_m5 might use the low 8 bits of devname to keep the model version number
AleX Pelosi962aedf2021-01-07 15:39:43 -0800175 * - 0 not M5, !=0 M5
176 */
177static inline int max_m5_check_devname(u16 devname)
178{
Jenny Hod5def242021-04-28 10:51:58 +0800179 const u16 radix = devname >> 8;
180
181 return radix == 0x62 || radix == 0x63;
AleX Pelosi962aedf2021-01-07 15:39:43 -0800182}
183
184/* b/177099997, handle TaskConfig = 351 */
185static inline int max_m5_cap_lsb(const struct max_m5_data *m5_data)
186{
187 return m5_data ? (1 << m5_data->cap_lsb) : 1;
188}
189
190static inline int max_m5_fg_model_version(const struct max_m5_data *m5_data)
191{
192 return m5_data ? m5_data->model_version : MAX_M5_INVALID_VERSION;
193}
194
195/*
196 * 0 reload, != 0 no reload
197 * always reload when the model version is not specified
198 */
199static inline int max_m5_fg_model_check_version(const struct max_m5_data *m5_data)
200{
201 if (!m5_data)
202 return 1;
203 if (m5_data->model_version == MAX_M5_INVALID_VERSION)
204 return 0;
205
206 return max_m5_model_read_version(m5_data) == m5_data->model_version;
207}
208
209/** ------------------------------------------------------------------------ */
210
Ken Tsou8acade12020-07-09 03:17:35 +0800211int max_m5_regmap_init(struct max17x0x_regmap *regmap,
212 struct i2c_client *primary);
213
214void *max_m5_init_data(struct device *dev, struct device_node *batt_node,
215 struct max17x0x_regmap *regmap);
Jenny Ho6a74c7a2023-03-16 05:47:15 +0800216void max_m5_free_data(struct max_m5_data *m5_data);
Ken Tsou8acade12020-07-09 03:17:35 +0800217
Ken Tsou8acade12020-07-09 03:17:35 +0800218int max_m5_load_state_data(struct max_m5_data *m5_data);
Ken Tsou8acade12020-07-09 03:17:35 +0800219int max_m5_save_state_data(struct max_m5_data *m5_data);
220
221/* read state from the gauge */
222int max_m5_model_read_state(struct max_m5_data *m5_data);
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800223int max_m5_model_check_state(struct max_m5_data *m5_data);
Ken Tsou8acade12020-07-09 03:17:35 +0800224
225/* load model to gauge */
226int max_m5_load_gauge_model(struct max_m5_data *m5_data);
227
AleX Pelosifed7fb12020-11-10 01:22:22 -0800228int max_m5_fixup_outliers(struct max1720x_drift_data *ddata,
229 struct max_m5_data *m5_data);
230
Ken Tsou8acade12020-07-09 03:17:35 +0800231ssize_t max_m5_model_state_cstr(char *buf, int max,
232 struct max_m5_data *m5_data);
233int max_m5_model_state_sscan(struct max_m5_data *m5_data, const char *buf,
234 int max);
235int max_m5_fg_model_sscan(struct max_m5_data *m5_data, const char *buf,
236 int max);
237int max_m5_fg_model_cstr(char *buf, int max, const struct max_m5_data *m5_data);
Jenny Ho5f92be52023-11-22 00:13:54 +0800238int max_m5_get_rc_switch_param(struct max_m5_data *m5_data, u16 *rc2_tempco, u16 *rc2_learncfg);
Ken Tsou8acade12020-07-09 03:17:35 +0800239
Jenny Hoc6bc5882021-02-18 09:21:21 +0800240/* read saved value */
241ssize_t max_m5_gmsr_state_cstr(char *buf, int max);
242
AleX Pelosi962aedf2021-01-07 15:39:43 -0800243/** ------------------------------------------------------------------------ */
244
AleX Pelosi32892282020-09-11 02:29:20 -0700245/*
246 *
247 */
248#if IS_ENABLED(CONFIG_MAX_M5)
249
250extern int max_m5_read_actual_input_current_ua(struct i2c_client *client,
251 int *iic);
Jack Wu83f98e32021-08-09 18:15:52 +0800252extern int max_m5_read_vbypass(struct i2c_client *client,
253 int *volt);
AleX Pelosi32892282020-09-11 02:29:20 -0700254
255extern int max_m5_reg_read(struct i2c_client *client, unsigned int reg,
Ken Tsou8acade12020-07-09 03:17:35 +0800256 unsigned int *val);
AleX Pelosi32892282020-09-11 02:29:20 -0700257extern int max_m5_reg_write(struct i2c_client *client, unsigned int reg,
Ken Tsou8acade12020-07-09 03:17:35 +0800258 unsigned int val);
AleX Pelosi32892282020-09-11 02:29:20 -0700259#else
260static inline int
261max_m5_read_actual_input_current_ua(struct i2c_client *client, int *iic)
262{
263 return -ENODEV;
264}
Ken Tsou8acade12020-07-09 03:17:35 +0800265
AleX Pelosi32892282020-09-11 02:29:20 -0700266static inline int
Jack Wu83f98e32021-08-09 18:15:52 +0800267max_m5_read_vbypass(struct i2c_client *client, int *volt)
268{
269 return -ENODEV;
270}
271
272static inline int
AleX Pelosi32892282020-09-11 02:29:20 -0700273max_m5_reg_read(struct i2c_client *client, unsigned int reg, unsigned int *val)
274{
275 return -ENODEV;
276}
277
278static inline int max_m5_reg_write(struct i2c_client *client, unsigned int reg,
279 unsigned int val)
280{
281 return -ENODEV;
282}
283
284
285#endif
286
287
288
289/* reach back into max1720x battery */
Ken Tsou8acade12020-07-09 03:17:35 +0800290void *max1720x_get_model_data(struct i2c_client *client);
291
AleX Pelosi32892282020-09-11 02:29:20 -0700292
Jack Wu83f98e32021-08-09 18:15:52 +0800293#endif