1 /*
2 * Copyright 2022 Google LLC
3 * Copyright 2023 Microsoft Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #ifndef ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_
9 #define ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_
10
11 /**
12 * @brief Fuel Gauge Interface
13 * @defgroup fuel_gauge_interface Fuel Gauge Interface
14 * @since 3.3
15 * @version 0.1.0
16 * @ingroup io_interfaces
17 * @{
18 */
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif /* __cplusplus */
23
24 #include <errno.h>
25 #include <stdbool.h>
26 #include <stddef.h>
27 #include <stdint.h>
28
29 #include <zephyr/device.h>
30
31 enum fuel_gauge_prop_type {
32 /** Runtime Dynamic Battery Parameters */
33 /**
34 * Provide a 1 minute average of the current on the battery.
35 * Does not check for flags or whether those values are bad readings.
36 * See driver instance header for details on implementation and
37 * how the average is calculated. Units in uA negative=discharging
38 */
39 FUEL_GAUGE_AVG_CURRENT = 0,
40
41 /** Used to cutoff the battery from the system - useful for storage/shipping of devices */
42 FUEL_GAUGE_BATTERY_CUTOFF,
43 /** Battery current (uA); negative=discharging */
44 FUEL_GAUGE_CURRENT,
45 /** Whether the battery underlying the fuel-gauge is cut off from charge */
46 FUEL_GAUGE_CHARGE_CUTOFF,
47 /** Cycle count in 1/100ths (number of charge/discharge cycles) */
48 FUEL_GAUGE_CYCLE_COUNT,
49 /** Connect state of battery */
50 FUEL_GAUGE_CONNECT_STATE,
51 /** General Error/Runtime Flags */
52 FUEL_GAUGE_FLAGS,
53 /** Full Charge Capacity in uAh (might change in some implementations to determine wear) */
54 FUEL_GAUGE_FULL_CHARGE_CAPACITY,
55 /** Is the battery physically present */
56 FUEL_GAUGE_PRESENT_STATE,
57 /** Remaining capacity in uAh */
58 FUEL_GAUGE_REMAINING_CAPACITY,
59 /** Remaining battery life time in minutes */
60 FUEL_GAUGE_RUNTIME_TO_EMPTY,
61 /** Remaining time in minutes until battery reaches full charge */
62 FUEL_GAUGE_RUNTIME_TO_FULL,
63 /** Retrieve word from SBS1.1 ManufactuerAccess */
64 FUEL_GAUGE_SBS_MFR_ACCESS,
65 /** Absolute state of charge (percent, 0-100) - expressed as % of design capacity */
66 FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE,
67 /** Relative state of charge (percent, 0-100) - expressed as % of full charge capacity */
68 FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE,
69 /** Temperature in 0.1 K */
70 FUEL_GAUGE_TEMPERATURE,
71 /** Battery voltage (uV) */
72 FUEL_GAUGE_VOLTAGE,
73 /** Battery Mode (flags) */
74 FUEL_GAUGE_SBS_MODE,
75 /** Battery desired Max Charging Current (uA) */
76 FUEL_GAUGE_CHARGE_CURRENT,
77 /** Battery desired Max Charging Voltage (uV) */
78 FUEL_GAUGE_CHARGE_VOLTAGE,
79 /** Alarm, Status and Error codes (flags) */
80 FUEL_GAUGE_STATUS,
81 /** Design Capacity (mAh or 10mWh) */
82 FUEL_GAUGE_DESIGN_CAPACITY,
83 /** Design Voltage (mV) */
84 FUEL_GAUGE_DESIGN_VOLTAGE,
85 /** AtRate (mA or 10 mW) */
86 FUEL_GAUGE_SBS_ATRATE,
87 /** AtRateTimeToFull (minutes) */
88 FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL,
89 /** AtRateTimeToEmpty (minutes) */
90 FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY,
91 /** AtRateOK (boolean) */
92 FUEL_GAUGE_SBS_ATRATE_OK,
93 /** Remaining Capacity Alarm (mAh or 10mWh) */
94 FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM,
95 /** Remaining Time Alarm (minutes) */
96 FUEL_GAUGE_SBS_REMAINING_TIME_ALARM,
97 /** Manufacturer of pack (1 byte length + 20 bytes data) */
98 FUEL_GAUGE_MANUFACTURER_NAME,
99 /** Name of pack (1 byte length + 20 bytes data) */
100 FUEL_GAUGE_DEVICE_NAME,
101 /** Chemistry (1 byte length + 4 bytes data) */
102 FUEL_GAUGE_DEVICE_CHEMISTRY,
103
104 /** Reserved to demark end of common fuel gauge properties */
105 FUEL_GAUGE_COMMON_COUNT,
106 /**
107 * Reserved to demark downstream custom properties - use this value as the actual value may
108 * change over future versions of this API
109 */
110 FUEL_GAUGE_CUSTOM_BEGIN,
111
112 /** Reserved to demark end of valid enum properties */
113 FUEL_GAUGE_PROP_MAX = UINT16_MAX,
114 };
115
116 typedef uint16_t fuel_gauge_prop_t;
117
118 /** Property field to value/type union */
119 union fuel_gauge_prop_val {
120 /* Fields have the format: */
121 /* FUEL_GAUGE_PROPERTY_FIELD */
122 /* type property_field; */
123
124 /* Dynamic Battery Info */
125 /** FUEL_GAUGE_AVG_CURRENT */
126 int avg_current;
127 /** FUEL_GAUGE_CHARGE_CUTOFF */
128 bool cutoff;
129 /** FUEL_GAUGE_CURRENT */
130 int current;
131 /** FUEL_GAUGE_CYCLE_COUNT */
132 uint32_t cycle_count;
133 /** FUEL_GAUGE_FLAGS */
134 uint32_t flags;
135 /** FUEL_GAUGE_FULL_CHARGE_CAPACITY */
136 uint32_t full_charge_capacity;
137 /** FUEL_GAUGE_REMAINING_CAPACITY */
138 uint32_t remaining_capacity;
139 /** FUEL_GAUGE_RUNTIME_TO_EMPTY */
140 uint32_t runtime_to_empty;
141 /** FUEL_GAUGE_RUNTIME_TO_FULL */
142 uint32_t runtime_to_full;
143 /** FUEL_GAUGE_SBS_MFR_ACCESS */
144 uint16_t sbs_mfr_access_word;
145 /** FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE */
146 uint8_t absolute_state_of_charge;
147 /** FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE */
148 uint8_t relative_state_of_charge;
149 /** FUEL_GAUGE_TEMPERATURE */
150 uint16_t temperature;
151 /** FUEL_GAUGE_VOLTAGE */
152 int voltage;
153 /** FUEL_GAUGE_SBS_MODE */
154 uint16_t sbs_mode;
155 /** FUEL_GAUGE_CHARGE_CURRENT */
156 uint32_t chg_current;
157 /** FUEL_GAUGE_CHARGE_VOLTAGE */
158 uint32_t chg_voltage;
159 /** FUEL_GAUGE_STATUS */
160 uint16_t fg_status;
161 /** FUEL_GAUGE_DESIGN_CAPACITY */
162 uint16_t design_cap;
163 /** FUEL_GAUGE_DESIGN_VOLTAGE */
164 uint16_t design_volt;
165 /** FUEL_GAUGE_SBS_ATRATE */
166 int16_t sbs_at_rate;
167 /** FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL */
168 uint16_t sbs_at_rate_time_to_full;
169 /** FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY */
170 uint16_t sbs_at_rate_time_to_empty;
171 /** FUEL_GAUGE_SBS_ATRATE_OK */
172 bool sbs_at_rate_ok;
173 /** FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM */
174 uint16_t sbs_remaining_capacity_alarm;
175 /** FUEL_GAUGE_SBS_REMAINING_TIME_ALARM */
176 uint16_t sbs_remaining_time_alarm;
177 };
178
179 /**
180 * Data structures for reading SBS buffer properties
181 */
182 #define SBS_GAUGE_MANUFACTURER_NAME_MAX_SIZE 20
183 #define SBS_GAUGE_DEVICE_NAME_MAX_SIZE 20
184 #define SBS_GAUGE_DEVICE_CHEMISTRY_MAX_SIZE 4
185
186 struct sbs_gauge_manufacturer_name {
187 uint8_t manufacturer_name_length;
188 char manufacturer_name[SBS_GAUGE_MANUFACTURER_NAME_MAX_SIZE];
189 } __packed;
190
191 struct sbs_gauge_device_name {
192 uint8_t device_name_length;
193 char device_name[SBS_GAUGE_DEVICE_NAME_MAX_SIZE];
194 } __packed;
195
196 struct sbs_gauge_device_chemistry {
197 uint8_t device_chemistry_length;
198 char device_chemistry[SBS_GAUGE_DEVICE_CHEMISTRY_MAX_SIZE];
199 } __packed;
200
201 /**
202 * @typedef fuel_gauge_get_property_t
203 * @brief Callback API for getting a fuel_gauge property.
204 *
205 * See fuel_gauge_get_property() for argument description
206 */
207 typedef int (*fuel_gauge_get_property_t)(const struct device *dev, fuel_gauge_prop_t prop,
208 union fuel_gauge_prop_val *val);
209
210 /**
211 * @typedef fuel_gauge_set_property_t
212 * @brief Callback API for setting a fuel_gauge property.
213 *
214 * See fuel_gauge_set_property() for argument description
215 */
216 typedef int (*fuel_gauge_set_property_t)(const struct device *dev, fuel_gauge_prop_t prop,
217 union fuel_gauge_prop_val val);
218
219 /**
220 * @typedef fuel_gauge_get_buffer_property_t
221 * @brief Callback API for getting a fuel_gauge buffer property.
222 *
223 * See fuel_gauge_get_buffer_property() for argument description
224 */
225 typedef int (*fuel_gauge_get_buffer_property_t)(const struct device *dev,
226 fuel_gauge_prop_t prop_type,
227 void *dst, size_t dst_len);
228
229 /**
230 * @typedef fuel_gauge_battery_cutoff_t
231 * @brief Callback API for doing a battery cutoff.
232 *
233 * See fuel_gauge_battery_cutoff() for argument description
234 */
235 typedef int (*fuel_gauge_battery_cutoff_t)(const struct device *dev);
236
237 /* Caching is entirely on the onus of the client */
238
239 __subsystem struct fuel_gauge_driver_api {
240 /**
241 * Note: Historically this API allowed drivers to implement a custom multi-get/set property
242 * function, this was added so drivers could potentially optimize batch read with their
243 * specific chip. However, it was removed because of no existing concrete case upstream.
244 * If this need is demonstrated, we can add this back in as an API field.
245 */
246 fuel_gauge_get_property_t get_property;
247 fuel_gauge_set_property_t set_property;
248 fuel_gauge_get_buffer_property_t get_buffer_property;
249 fuel_gauge_battery_cutoff_t battery_cutoff;
250 };
251
252 /**
253 * @brief Fetch a battery fuel-gauge property
254 *
255 * @param dev Pointer to the battery fuel-gauge device
256 * @param prop Type of property to be fetched from device
257 * @param val pointer to a union fuel_gauge_prop_val where the property is read into from the
258 * fuel gauge device.
259 * @return 0 if successful, negative errno code if failure.
260 */
261 __syscall int fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
262 union fuel_gauge_prop_val *val);
263
z_impl_fuel_gauge_get_prop(const struct device * dev,fuel_gauge_prop_t prop,union fuel_gauge_prop_val * val)264 static inline int z_impl_fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
265 union fuel_gauge_prop_val *val)
266 {
267 const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
268
269 if (api->get_property == NULL) {
270 return -ENOSYS;
271 }
272
273 return api->get_property(dev, prop, val);
274 }
275
276 /**
277 * @brief Fetch multiple battery fuel-gauge properties. The default implementation is the same as
278 * calling fuel_gauge_get_prop() multiple times. A driver may implement the `get_properties` field
279 * of the fuel gauge driver APIs struct to override this implementation.
280 *
281 * @param dev Pointer to the battery fuel-gauge device
282 * @param props Array of the type of property to be fetched from device, each index corresponds
283 * to the same index of the vals input array.
284 * @param vals Pointer to array of union fuel_gauge_prop_val where the property is read into from
285 * the fuel gauge device. The vals array is not permuted.
286 * @param len number of properties in props & vals array
287 *
288 * @return 0 if successful, negative errno code of first failing property
289 */
290
291 __syscall int fuel_gauge_get_props(const struct device *dev, fuel_gauge_prop_t *props,
292 union fuel_gauge_prop_val *vals, size_t len);
z_impl_fuel_gauge_get_props(const struct device * dev,fuel_gauge_prop_t * props,union fuel_gauge_prop_val * vals,size_t len)293 static inline int z_impl_fuel_gauge_get_props(const struct device *dev,
294 fuel_gauge_prop_t *props,
295 union fuel_gauge_prop_val *vals, size_t len)
296 {
297 const struct fuel_gauge_driver_api *api = dev->api;
298
299 for (int i = 0; i < len; i++) {
300 int ret = api->get_property(dev, props[i], vals + i);
301
302 if (ret) {
303 return ret;
304 }
305 }
306
307 return 0;
308 }
309
310 /**
311 * @brief Set a battery fuel-gauge property
312 *
313 * @param dev Pointer to the battery fuel-gauge device
314 * @param prop Type of property that's being set
315 * @param val Value to set associated prop property.
316 *
317 * @return 0 if successful, negative errno code of first failing property
318 */
319 __syscall int fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop,
320 union fuel_gauge_prop_val val);
321
z_impl_fuel_gauge_set_prop(const struct device * dev,fuel_gauge_prop_t prop,union fuel_gauge_prop_val val)322 static inline int z_impl_fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop,
323 union fuel_gauge_prop_val val)
324 {
325 const struct fuel_gauge_driver_api *api = dev->api;
326
327 if (api->set_property == NULL) {
328 return -ENOSYS;
329 }
330
331 return api->set_property(dev, prop, val);
332 }
333 /**
334 * @brief Set a battery fuel-gauge property
335 *
336 * @param dev Pointer to the battery fuel-gauge device
337 * @param props Array of the type of property to be set, each index corresponds
338 * to the same index of the vals input array.
339 * @param vals Pointer to array of union fuel_gauge_prop_val where the property is written
340 * the fuel gauge device. The vals array is not permuted.
341 * @param len number of properties in props array
342 *
343 * @return return=0 if successful. Otherwise, return array index of failing property.
344 */
345 __syscall int fuel_gauge_set_props(const struct device *dev, fuel_gauge_prop_t *props,
346 union fuel_gauge_prop_val *vals, size_t len);
347
z_impl_fuel_gauge_set_props(const struct device * dev,fuel_gauge_prop_t * props,union fuel_gauge_prop_val * vals,size_t len)348 static inline int z_impl_fuel_gauge_set_props(const struct device *dev,
349 fuel_gauge_prop_t *props,
350 union fuel_gauge_prop_val *vals, size_t len)
351 {
352 for (int i = 0; i < len; i++) {
353 int ret = fuel_gauge_set_prop(dev, props[i], vals[i]);
354
355 if (ret) {
356 return ret;
357 }
358 }
359
360 return 0;
361 }
362
363 /**
364 * @brief Fetch a battery fuel-gauge buffer property
365 *
366 * @param dev Pointer to the battery fuel-gauge device
367 * @param prop_type Type of property to be fetched from device
368 * @param dst byte array or struct that will hold the buffer data that is read from the fuel gauge
369 * @param dst_len the length of the destination array in bytes
370 *
371 * @return return=0 if successful, return < 0 if getting property failed, return 0 on success
372 */
373
374 __syscall int fuel_gauge_get_buffer_prop(const struct device *dev, fuel_gauge_prop_t prop_type,
375 void *dst, size_t dst_len);
376
z_impl_fuel_gauge_get_buffer_prop(const struct device * dev,fuel_gauge_prop_t prop_type,void * dst,size_t dst_len)377 static inline int z_impl_fuel_gauge_get_buffer_prop(const struct device *dev,
378 fuel_gauge_prop_t prop_type,
379 void *dst, size_t dst_len)
380 {
381 const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
382
383 if (api->get_buffer_property == NULL) {
384 return -ENOSYS;
385 }
386
387 return api->get_buffer_property(dev, prop_type, dst, dst_len);
388 }
389
390 /**
391 * @brief Have fuel gauge cutoff its associated battery.
392 *
393 * @param dev Pointer to the battery fuel-gauge device
394 *
395 * @return return=0 if successful and battery cutoff is now in process, return < 0 if failed to do
396 * battery cutoff.
397 */
398 __syscall int fuel_gauge_battery_cutoff(const struct device *dev);
399
z_impl_fuel_gauge_battery_cutoff(const struct device * dev)400 static inline int z_impl_fuel_gauge_battery_cutoff(const struct device *dev)
401 {
402 const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
403
404 if (api->battery_cutoff == NULL) {
405 return -ENOSYS;
406 }
407
408 return api->battery_cutoff(dev);
409 }
410
411 /**
412 * @}
413 */
414
415 #ifdef __cplusplus
416 }
417 #endif /* __cplusplus */
418
419 #include <zephyr/syscalls/fuel_gauge.h>
420
421 #endif /* ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_ */
422