blob: 02d5b91df3070f0ef105d7de896db1bf25c4876a [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
AleX Pelosi962aedf2021-01-07 15:39:43 -080028#define MAX_M5_LOAD_MODEL_REQUEST 5
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
43#define MAX_M5_VFSOC 0xFF
44
AleX Pelosi962aedf2021-01-07 15:39:43 -080045/* model version */
46#define MAX_M5_INVALID_VERSION -1
47
48
Ken Tsou8acade12020-07-09 03:17:35 +080049/** ------------------------------------------------------------------------ */
50
51/*
AleX Pelosi76b63502020-11-03 16:49:44 -080052 * Custom parameters are updated while the device is runnig.
53 * NOTE: a subset (model_state_save) is saved to permanent storage every "n"
54 * cycles and restored when the model is reloaded (usually on POR).
55 * TODO: handle switching between RC1 and RC2 model types.
Ken Tsou8acade12020-07-09 03:17:35 +080056 */
57struct max_m5_custom_parameters {
58 u16 iavg_empty; /* WV */
59 u16 relaxcfg;
60 u16 learncfg;
61 u16 config;
62 u16 config2;
63 u16 fullsocthr;
64 u16 fullcaprep; /* WV */
65 u16 designcap;
66 u16 dpacc; /* WV */
67 u16 dqacc; /* WV */
68 u16 fullcapnom; /* WV */
69 u16 v_empty;
70 u16 qresidual00; /* WV */
71 u16 qresidual10; /* WV */
72 u16 qresidual20; /* WV */
73 u16 qresidual30; /* WV */
74 u16 rcomp0; /* WV */
75 u16 tempco; /* WV */
76 u16 ichgterm;
77 u16 tgain;
78 u16 toff;
79 u16 tcurve; /* write to 0x00B9 */
80 u16 misccfg; /* 0x9d0 for internal current sense, 0x8d0 external */
81
82 u16 atrate;
83 u16 convgcfg;
84 u16 filtercfg; /* write to 0x0029 */
AleX Pelosi962aedf2021-01-07 15:39:43 -080085 u16 taskperiod;
Jenny Hoe8b877c2022-01-10 03:27:53 +080086 u16 cgain;
Ken Tsou8acade12020-07-09 03:17:35 +080087} __attribute__((packed));
88
AleX Pelosi76b63502020-11-03 16:49:44 -080089/* this is what is saved and restored to/from GMSR */
Ken Tsou8acade12020-07-09 03:17:35 +080090struct model_state_save {
91 u16 rcomp0;
92 u16 tempco;
93 u16 fullcaprep;
94 u16 cycles;
95 u16 fullcapnom;
96 u16 qresidual00;
97 u16 qresidual10;
98 u16 qresidual20;
99 u16 qresidual30;
Jenny Hodc6c8a02021-10-29 06:14:33 +0800100 u16 cv_mixcap;
Ken Tsou8acade12020-07-09 03:17:35 +0800101 u16 halftime;
Jenny Hof77200e2021-05-31 17:32:55 +0800102 u8 crc;
AleX Pelosi76b63502020-11-03 16:49:44 -0800103} __attribute__((packed));
Ken Tsou8acade12020-07-09 03:17:35 +0800104
105struct max_m5_data {
106 struct device *dev;
AleX Pelosi76b63502020-11-03 16:49:44 -0800107 struct max17x0x_regmap *regmap;
AleX Pelosi962aedf2021-01-07 15:39:43 -0800108 int cap_lsb; /* b/177099997 */
Ken Tsou8acade12020-07-09 03:17:35 +0800109
AleX Pelosi76b63502020-11-03 16:49:44 -0800110 /* initial parameters are in device tree they are also learned */
Ken Tsou8acade12020-07-09 03:17:35 +0800111 struct max_m5_custom_parameters parameters;
112 u16 cycles;
Jenny Hodc6c8a02021-10-29 06:14:33 +0800113 u16 cv_mixcap;
Ken Tsou8acade12020-07-09 03:17:35 +0800114 u16 halftime;
115
Ken Tsou8acade12020-07-09 03:17:35 +0800116 int custom_model_size;
117 u16 *custom_model;
AleX Pelosi962aedf2021-01-07 15:39:43 -0800118 u32 model_version;
Jenny Ho7c691da2021-05-19 06:15:54 +0800119 bool force_reset_model_data;
Ken Tsou8acade12020-07-09 03:17:35 +0800120
AleX Pelosi76b63502020-11-03 16:49:44 -0800121 /* to/from GMSR */
Ken Tsou8acade12020-07-09 03:17:35 +0800122 struct model_state_save model_save;
123};
124
AleX Pelosi32892282020-09-11 02:29:20 -0700125/** ------------------------------------------------------------------------ */
126
AleX Pelosi962aedf2021-01-07 15:39:43 -0800127int max_m5_model_read_version(const struct max_m5_data *m5_data);
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800128int max_m5_model_get_cap_lsb(const struct max_m5_data *m5_data);
Jenny Hoc6bc5882021-02-18 09:21:21 +0800129int max_m5_reset_state_data(struct max_m5_data *m5_data);
130int max_m5_needs_reset_model_data(const struct max_m5_data *m5_data);
AleX Pelosi962aedf2021-01-07 15:39:43 -0800131
132/*
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800133 * max_m5 might use the low 8 bits of devname to keep the model version number
AleX Pelosi962aedf2021-01-07 15:39:43 -0800134 * - 0 not M5, !=0 M5
135 */
136static inline int max_m5_check_devname(u16 devname)
137{
Jenny Hod5def242021-04-28 10:51:58 +0800138 const u16 radix = devname >> 8;
139
140 return radix == 0x62 || radix == 0x63;
AleX Pelosi962aedf2021-01-07 15:39:43 -0800141}
142
143/* b/177099997, handle TaskConfig = 351 */
144static inline int max_m5_cap_lsb(const struct max_m5_data *m5_data)
145{
146 return m5_data ? (1 << m5_data->cap_lsb) : 1;
147}
148
149static inline int max_m5_fg_model_version(const struct max_m5_data *m5_data)
150{
151 return m5_data ? m5_data->model_version : MAX_M5_INVALID_VERSION;
152}
153
154/*
155 * 0 reload, != 0 no reload
156 * always reload when the model version is not specified
157 */
158static inline int max_m5_fg_model_check_version(const struct max_m5_data *m5_data)
159{
160 if (!m5_data)
161 return 1;
162 if (m5_data->model_version == MAX_M5_INVALID_VERSION)
163 return 0;
164
165 return max_m5_model_read_version(m5_data) == m5_data->model_version;
166}
167
168/** ------------------------------------------------------------------------ */
169
Ken Tsou8acade12020-07-09 03:17:35 +0800170int max_m5_regmap_init(struct max17x0x_regmap *regmap,
171 struct i2c_client *primary);
172
173void *max_m5_init_data(struct device *dev, struct device_node *batt_node,
174 struct max17x0x_regmap *regmap);
175void max_m5_free_data(void *data);
176
Ken Tsou8acade12020-07-09 03:17:35 +0800177int max_m5_load_state_data(struct max_m5_data *m5_data);
Ken Tsou8acade12020-07-09 03:17:35 +0800178int max_m5_save_state_data(struct max_m5_data *m5_data);
179
180/* read state from the gauge */
181int max_m5_model_read_state(struct max_m5_data *m5_data);
AleX Pelosifc6f66d2021-01-12 18:14:48 -0800182int max_m5_model_check_state(struct max_m5_data *m5_data);
Ken Tsou8acade12020-07-09 03:17:35 +0800183
184/* load model to gauge */
185int max_m5_load_gauge_model(struct max_m5_data *m5_data);
186
AleX Pelosifed7fb12020-11-10 01:22:22 -0800187int max_m5_fixup_outliers(struct max1720x_drift_data *ddata,
188 struct max_m5_data *m5_data);
189
Ken Tsou8acade12020-07-09 03:17:35 +0800190ssize_t max_m5_model_state_cstr(char *buf, int max,
191 struct max_m5_data *m5_data);
192int max_m5_model_state_sscan(struct max_m5_data *m5_data, const char *buf,
193 int max);
194int max_m5_fg_model_sscan(struct max_m5_data *m5_data, const char *buf,
195 int max);
196int max_m5_fg_model_cstr(char *buf, int max, const struct max_m5_data *m5_data);
197
Jenny Hoc6bc5882021-02-18 09:21:21 +0800198/* read saved value */
199ssize_t max_m5_gmsr_state_cstr(char *buf, int max);
200
AleX Pelosi962aedf2021-01-07 15:39:43 -0800201/** ------------------------------------------------------------------------ */
202
AleX Pelosi32892282020-09-11 02:29:20 -0700203/*
204 *
205 */
206#if IS_ENABLED(CONFIG_MAX_M5)
207
208extern int max_m5_read_actual_input_current_ua(struct i2c_client *client,
209 int *iic);
Jack Wu83f98e32021-08-09 18:15:52 +0800210extern int max_m5_read_vbypass(struct i2c_client *client,
211 int *volt);
AleX Pelosi32892282020-09-11 02:29:20 -0700212
213extern int max_m5_reg_read(struct i2c_client *client, unsigned int reg,
Ken Tsou8acade12020-07-09 03:17:35 +0800214 unsigned int *val);
AleX Pelosi32892282020-09-11 02:29:20 -0700215extern int max_m5_reg_write(struct i2c_client *client, unsigned int reg,
Ken Tsou8acade12020-07-09 03:17:35 +0800216 unsigned int val);
AleX Pelosi32892282020-09-11 02:29:20 -0700217#else
218static inline int
219max_m5_read_actual_input_current_ua(struct i2c_client *client, int *iic)
220{
221 return -ENODEV;
222}
Ken Tsou8acade12020-07-09 03:17:35 +0800223
AleX Pelosi32892282020-09-11 02:29:20 -0700224static inline int
Jack Wu83f98e32021-08-09 18:15:52 +0800225max_m5_read_vbypass(struct i2c_client *client, int *volt)
226{
227 return -ENODEV;
228}
229
230static inline int
AleX Pelosi32892282020-09-11 02:29:20 -0700231max_m5_reg_read(struct i2c_client *client, unsigned int reg, unsigned int *val)
232{
233 return -ENODEV;
234}
235
236static inline int max_m5_reg_write(struct i2c_client *client, unsigned int reg,
237 unsigned int val)
238{
239 return -ENODEV;
240}
241
242
243#endif
244
245
246
247/* reach back into max1720x battery */
Ken Tsou8acade12020-07-09 03:17:35 +0800248void *max1720x_get_model_data(struct i2c_client *client);
249
AleX Pelosi32892282020-09-11 02:29:20 -0700250
Jack Wu83f98e32021-08-09 18:15:52 +0800251#endif