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