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