1 /*
2  * Copyright 2023 Cirrus Logic, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Charger APIs
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_
13 #define ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_
14 
15 /**
16  * @brief Charger Interface
17  * @defgroup charger_interface Charger Interface
18  * @ingroup io_interfaces
19  * @{
20  */
21 
22 #include <stdbool.h>
23 #include <stddef.h>
24 #include <stdint.h>
25 
26 #include <zephyr/device.h>
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif /* __cplusplus */
31 
32 /**
33  * @brief Runtime Dynamic Battery Parameters
34  */
35 enum charger_property {
36 	/** Indicates if external supply is present for the charger. */
37 	/** Value should be of type enum charger_online */
38 	CHARGER_PROP_ONLINE = 0,
39 	/** Reports whether or not a battery is present. */
40 	/** Value should be of type bool*/
41 	CHARGER_PROP_PRESENT,
42 	/** Represents the charging status of the charger. */
43 	/** Value should be of type enum charger_status */
44 	CHARGER_PROP_STATUS,
45 	/** Represents the charging algo type of the charger. */
46 	/** Value should be of type enum charger_charge_type */
47 	CHARGER_PROP_CHARGE_TYPE,
48 	/** Represents the health of the charger. */
49 	/** Value should be of type enum charger_health */
50 	CHARGER_PROP_HEALTH,
51 	/** Configuration of current sink used for charging in µA */
52 	CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA,
53 	/** Configuration of current sink used for conditioning in µA */
54 	CHARGER_PROP_PRECHARGE_CURRENT_UA,
55 	/** Configuration of charge termination target in µA */
56 	CHARGER_PROP_CHARGE_TERM_CURRENT_UA,
57 	/** Configuration of charge voltage regulation target in µV */
58 	CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV,
59 	/**
60 	 * Configuration of the input current regulation target in µA
61 	 *
62 	 * This value is a rising current threshold that is regulated by reducing the charge
63 	 * current output
64 	 */
65 	CHARGER_PROP_INPUT_REGULATION_CURRENT_UA,
66 	/**
67 	 * Configuration of the input voltage regulation target in µV
68 	 *
69 	 * This value is a falling voltage threshold that is regulated by reducing the charge
70 	 * current output
71 	 */
72 	CHARGER_PROP_INPUT_REGULATION_VOLTAGE_UV,
73 	/**
74 	 * Configuration to issue a notification to the system based on the input current
75 	 * level and timing
76 	 *
77 	 * Value should be of type struct charger_current_notifier
78 	 */
79 	CHARGER_PROP_INPUT_CURRENT_NOTIFICATION,
80 	/**
81 	 * Configuration to issue a notification to the system based on the battery discharge
82 	 * current level and timing
83 	 *
84 	 * Value should be of type struct charger_current_notifier
85 	 */
86 	CHARGER_PROP_DISCHARGE_CURRENT_NOTIFICATION,
87 	/**
88 	 * Configuration of the falling system voltage threshold where a notification
89 	 * is issued to the system, measured in µV
90 	 */
91 	CHARGER_PROP_SYSTEM_VOLTAGE_NOTIFICATION_UV,
92 	/**
93 	 * Configuration to issue a notification to the system based on the charger status change
94 	 *
95 	 * Value should be of type charger_status_notifier_t
96 	 */
97 	CHARGER_PROP_STATUS_NOTIFICATION,
98 	/**
99 	 * Configuration to issue a notification to the system based on the charger online change
100 	 *
101 	 * Value should be of type charger_online_notifier_t
102 	 */
103 	CHARGER_PROP_ONLINE_NOTIFICATION,
104 	/** Reserved to demark end of common charger properties */
105 	CHARGER_PROP_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 	CHARGER_PROP_CUSTOM_BEGIN = CHARGER_PROP_COMMON_COUNT + 1,
111 	/** Reserved to demark end of valid enum properties */
112 	CHARGER_PROP_MAX = UINT16_MAX,
113 };
114 
115 /**
116  * @typedef charger_prop_t
117  * @brief A charger property's identifier
118  *
119  * See charger_property for a list of identifiers
120  */
121 typedef uint16_t charger_prop_t;
122 
123 /**
124  * @brief External supply states
125  */
126 enum charger_online {
127 	/** External supply not present */
128 	CHARGER_ONLINE_OFFLINE = 0,
129 	/** External supply is present and of fixed output */
130 	CHARGER_ONLINE_FIXED,
131 	/** External supply is present and of programmable output*/
132 	CHARGER_ONLINE_PROGRAMMABLE,
133 };
134 
135 /**
136  * @brief Charging states
137  */
138 enum charger_status {
139 	/** Charging device state is unknown */
140 	CHARGER_STATUS_UNKNOWN = 0,
141 	/** Charging device is charging a battery */
142 	CHARGER_STATUS_CHARGING,
143 	/** Charging device is not able to charge a battery */
144 	CHARGER_STATUS_DISCHARGING,
145 	/** Charging device is not charging a battery */
146 	CHARGER_STATUS_NOT_CHARGING,
147 	/** The battery is full and the charging device will not attempt charging */
148 	CHARGER_STATUS_FULL,
149 };
150 
151 /**
152  * @brief Charge algorithm types
153  */
154 enum charger_charge_type {
155 	/** Charge type is unknown */
156 	CHARGER_CHARGE_TYPE_UNKNOWN = 0,
157 	/** Charging is not occurring */
158 	CHARGER_CHARGE_TYPE_NONE,
159 	/**
160 	 * Charging is occurring at the slowest desired charge rate,
161 	 * typically for battery detection or preconditioning
162 	 */
163 	CHARGER_CHARGE_TYPE_TRICKLE,
164 	/** Charging is occurring at the fastest desired charge rate */
165 	CHARGER_CHARGE_TYPE_FAST,
166 	/** Charging is occurring at a moderate charge rate */
167 	CHARGER_CHARGE_TYPE_STANDARD,
168 	/*
169 	 * Charging is being dynamically adjusted by the charger device
170 	 */
171 	CHARGER_CHARGE_TYPE_ADAPTIVE,
172 	/*
173 	 * Charging is occurring at a reduced charge rate to preserve
174 	 * battery health
175 	 */
176 	CHARGER_CHARGE_TYPE_LONGLIFE,
177 	/*
178 	 * The charger device is being bypassed and the power conversion
179 	 * is being handled externally, typically by a "smart" wall adaptor
180 	 */
181 	CHARGER_CHARGE_TYPE_BYPASS,
182 };
183 
184 /**
185  * @brief Charger health conditions
186  *
187  * These conditions determine the ability to, or the rate of, charge
188  */
189 enum charger_health {
190 	/** Charger health condition is unknown */
191 	CHARGER_HEALTH_UNKNOWN = 0,
192 	/** Charger health condition is good */
193 	CHARGER_HEALTH_GOOD,
194 	/** The charger device is overheated */
195 	CHARGER_HEALTH_OVERHEAT,
196 	/** The battery voltage has exceeded its overvoltage threshold */
197 	CHARGER_HEALTH_OVERVOLTAGE,
198 	/**
199 	 * The battery or charger device is experiencing an unspecified
200 	 * failure.
201 	 */
202 	CHARGER_HEALTH_UNSPEC_FAILURE,
203 	/** The battery temperature is below the "cold" threshold */
204 	CHARGER_HEALTH_COLD,
205 	/** The charger device's watchdog timer has expired */
206 	CHARGER_HEALTH_WATCHDOG_TIMER_EXPIRE,
207 	/** The charger device's safety timer has expired */
208 	CHARGER_HEALTH_SAFETY_TIMER_EXPIRE,
209 	/** The charger device requires calibration */
210 	CHARGER_HEALTH_CALIBRATION_REQUIRED,
211 	/** The battery temperature is in the "warm" range */
212 	CHARGER_HEALTH_WARM,
213 	/** The battery temperature is in the "cool" range */
214 	CHARGER_HEALTH_COOL,
215 	/** The battery temperature is below the "hot" threshold */
216 	CHARGER_HEALTH_HOT,
217 	/** The charger device does not detect a battery */
218 	CHARGER_HEALTH_NO_BATTERY,
219 };
220 
221 /**
222  * @brief Charger severity levels for system notifications
223  */
224 enum charger_notification_severity {
225 	/** Most severe level, typically triggered instantaneously */
226 	CHARGER_SEVERITY_PEAK = 0,
227 	/** More severe than the warning level, less severe than peak */
228 	CHARGER_SEVERITY_CRITICAL,
229 	/** Base severity level */
230 	CHARGER_SEVERITY_WARNING,
231 };
232 
233 /**
234  * @brief The input current thresholds for the charger to notify the system
235  */
236 struct charger_current_notifier {
237 	/** The severity of the notification where CHARGER_SEVERITY_PEAK is the most severe */
238 	uint8_t severity;
239 	/** The current threshold to be exceeded */
240 	uint32_t current_ua;
241 	/** The duration of excess current before notifying the system */
242 	uint32_t duration_us;
243 };
244 
245 /**
246  * @brief The charger status change callback to notify the system
247  *
248  * @param status Current charging state
249  */
250 typedef void (*charger_status_notifier_t)(enum charger_status status);
251 
252 /**
253  * @brief The charger online change callback to notify the system
254  *
255  * @param online Current external supply state
256  */
257 typedef void (*charger_online_notifier_t)(enum charger_online online);
258 
259 /**
260  * @brief container for a charger_property value
261  *
262  */
263 union charger_propval {
264 	/* Fields have the format: */
265 	/* CHARGER_PROPERTY_FIELD */
266 	/* type property_field; */
267 
268 	/** CHARGER_PROP_ONLINE */
269 	enum charger_online online;
270 	/** CHARGER_PROP_PRESENT */
271 	bool present;
272 	/** CHARGER_PROP_STATUS */
273 	enum charger_status status;
274 	/** CHARGER_PROP_CHARGE_TYPE */
275 	enum charger_charge_type charge_type;
276 	/** CHARGER_PROP_HEALTH */
277 	enum charger_health health;
278 	/** CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA */
279 	uint32_t const_charge_current_ua;
280 	/** CHARGER_PROP_PRECHARGE_CURRENT_UA */
281 	uint32_t precharge_current_ua;
282 	/** CHARGER_PROP_CHARGE_TERM_CURRENT_UA */
283 	uint32_t charge_term_current_ua;
284 	/** CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV */
285 	uint32_t const_charge_voltage_uv;
286 	/** CHARGER_PROP_INPUT_REGULATION_CURRENT_UA */
287 	uint32_t input_current_regulation_current_ua;
288 	/** CHARGER_PROP_INPUT_REGULATION_VOLTAGE_UV */
289 	uint32_t input_voltage_regulation_voltage_uv;
290 	/** CHARGER_PROP_INPUT_CURRENT_NOTIFICATION */
291 	struct charger_current_notifier input_current_notification;
292 	/** CHARGER_PROP_DISCHARGE_CURRENT_NOTIFICATION */
293 	struct charger_current_notifier discharge_current_notification;
294 	/** CHARGER_PROP_SYSTEM_VOLTAGE_NOTIFICATION_UV */
295 	uint32_t system_voltage_notification;
296 	/** CHARGER_PROP_STATUS_NOTIFICATION */
297 	charger_status_notifier_t status_notification;
298 	/** CHARGER_PROP_ONLINE_NOTIFICATION */
299 	charger_online_notifier_t online_notification;
300 };
301 
302 /**
303  * @typedef charger_get_property_t
304  * @brief Callback API for getting a charger property.
305  *
306  * See charger_get_property() for argument description
307  */
308 typedef int (*charger_get_property_t)(const struct device *dev, const charger_prop_t prop,
309 				      union charger_propval *val);
310 
311 /**
312  * @typedef charger_set_property_t
313  * @brief Callback API for setting a charger property.
314  *
315  * See charger_set_property() for argument description
316  */
317 typedef int (*charger_set_property_t)(const struct device *dev, const charger_prop_t prop,
318 				      const union charger_propval *val);
319 
320 /**
321  * @typedef charger_charge_enable_t
322  * @brief Callback API enabling or disabling a charge cycle.
323  *
324  * See charger_charge_enable() for argument description
325  */
326 typedef int (*charger_charge_enable_t)(const struct device *dev, const bool enable);
327 
328 /**
329  * @brief Charging device API
330  *
331  * Caching is entirely on the onus of the client
332  */
333 __subsystem struct charger_driver_api {
334 	charger_get_property_t get_property;
335 	charger_set_property_t set_property;
336 	charger_charge_enable_t charge_enable;
337 };
338 
339 /**
340  * @brief Fetch a battery charger property
341  *
342  * @param dev Pointer to the battery charger device
343  * @param prop Charger property to get
344  * @param val Pointer to charger_propval union
345  *
346  * @retval 0 if successful
347  * @retval < 0 if getting property failed
348  */
349 __syscall int charger_get_prop(const struct device *dev, const charger_prop_t prop,
350 			       union charger_propval *val);
351 
z_impl_charger_get_prop(const struct device * dev,const charger_prop_t prop,union charger_propval * val)352 static inline int z_impl_charger_get_prop(const struct device *dev, const charger_prop_t prop,
353 					  union charger_propval *val)
354 {
355 	const struct charger_driver_api *api = (const struct charger_driver_api *)dev->api;
356 
357 	return api->get_property(dev, prop, val);
358 }
359 
360 /**
361  * @brief Set a battery charger property
362  *
363  * @param dev Pointer to the battery charger device
364  * @param prop Charger property to set
365  * @param val Pointer to charger_propval union
366  *
367  * @retval 0 if successful
368  * @retval < 0 if setting property failed
369  */
370 __syscall int charger_set_prop(const struct device *dev, const charger_prop_t prop,
371 			       const union charger_propval *val);
372 
z_impl_charger_set_prop(const struct device * dev,const charger_prop_t prop,const union charger_propval * val)373 static inline int z_impl_charger_set_prop(const struct device *dev, const charger_prop_t prop,
374 					  const union charger_propval *val)
375 {
376 	const struct charger_driver_api *api = (const struct charger_driver_api *)dev->api;
377 
378 	return api->set_property(dev, prop, val);
379 }
380 
381 /**
382  * @brief Enable or disable a charge cycle
383  *
384  * @param dev Pointer to the battery charger device
385  * @param enable true enables a charge cycle, false disables a charge cycle
386  *
387  * @retval 0 if successful
388  * @retval -EIO if communication with the charger failed
389  * @retval -EINVAL if the conditions for initiating charging are invalid
390  */
391 __syscall int charger_charge_enable(const struct device *dev, const bool enable);
392 
z_impl_charger_charge_enable(const struct device * dev,const bool enable)393 static inline int z_impl_charger_charge_enable(const struct device *dev, const bool enable)
394 {
395 	const struct charger_driver_api *api = (const struct charger_driver_api *)dev->api;
396 
397 	return api->charge_enable(dev, enable);
398 }
399 
400 /**
401  * @}
402  */
403 
404 #ifdef __cplusplus
405 }
406 #endif /* __cplusplus */
407 
408 #include <zephyr/syscalls/charger.h>
409 
410 #endif /* ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_ */
411