blob: 305e97b278ff41353d1c44689d1533d6c63a4992 [file] [log] [blame]
/*
* Copyright 2022 Google LLC
* Copyright 2023 Microsoft Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_
#define ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_
/**
* @brief Fuel Gauge Interface
* @defgroup fuel_gauge_interface Fuel Gauge Interface
* @since 3.3
* @version 0.1.0
* @ingroup io_interfaces
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <zephyr/device.h>
enum fuel_gauge_prop_type {
/** Runtime Dynamic Battery Parameters */
/**
* Provide a 1 minute average of the current on the battery.
* Does not check for flags or whether those values are bad readings.
* See driver instance header for details on implementation and
* how the average is calculated. Units in uA negative=discharging
*/
FUEL_GAUGE_AVG_CURRENT = 0,
/** Used to cutoff the battery from the system - useful for storage/shipping of devices */
FUEL_GAUGE_BATTERY_CUTOFF,
/** Battery current (uA); negative=discharging */
FUEL_GAUGE_CURRENT,
/** Whether the battery underlying the fuel-gauge is cut off from charge */
FUEL_GAUGE_CHARGE_CUTOFF,
/** Cycle count in 1/100ths (number of charge/discharge cycles) */
FUEL_GAUGE_CYCLE_COUNT,
/** Connect state of battery */
FUEL_GAUGE_CONNECT_STATE,
/** General Error/Runtime Flags */
FUEL_GAUGE_FLAGS,
/** Full Charge Capacity in uAh (might change in some implementations to determine wear) */
FUEL_GAUGE_FULL_CHARGE_CAPACITY,
/** Is the battery physically present */
FUEL_GAUGE_PRESENT_STATE,
/** Remaining capacity in uAh */
FUEL_GAUGE_REMAINING_CAPACITY,
/** Remaining battery life time in minutes */
FUEL_GAUGE_RUNTIME_TO_EMPTY,
/** Remaining time in minutes until battery reaches full charge */
FUEL_GAUGE_RUNTIME_TO_FULL,
/** Retrieve word from SBS1.1 ManufactuerAccess */
FUEL_GAUGE_SBS_MFR_ACCESS,
/** Absolute state of charge (percent, 0-100) - expressed as % of design capacity */
FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE,
/** Relative state of charge (percent, 0-100) - expressed as % of full charge capacity */
FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE,
/** Temperature in 0.1 K */
FUEL_GAUGE_TEMPERATURE,
/** Battery voltage (uV) */
FUEL_GAUGE_VOLTAGE,
/** Battery Mode (flags) */
FUEL_GAUGE_SBS_MODE,
/** Battery desired Max Charging Current (uA) */
FUEL_GAUGE_CHARGE_CURRENT,
/** Battery desired Max Charging Voltage (uV) */
FUEL_GAUGE_CHARGE_VOLTAGE,
/** Alarm, Status and Error codes (flags) */
FUEL_GAUGE_STATUS,
/** Design Capacity (mAh or 10mWh) */
FUEL_GAUGE_DESIGN_CAPACITY,
/** Design Voltage (mV) */
FUEL_GAUGE_DESIGN_VOLTAGE,
/** AtRate (mA or 10 mW) */
FUEL_GAUGE_SBS_ATRATE,
/** AtRateTimeToFull (minutes) */
FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL,
/** AtRateTimeToEmpty (minutes) */
FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY,
/** AtRateOK (boolean) */
FUEL_GAUGE_SBS_ATRATE_OK,
/** Remaining Capacity Alarm (mAh or 10mWh) */
FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM,
/** Remaining Time Alarm (minutes) */
FUEL_GAUGE_SBS_REMAINING_TIME_ALARM,
/** Manufacturer of pack (1 byte length + 20 bytes data) */
FUEL_GAUGE_MANUFACTURER_NAME,
/** Name of pack (1 byte length + 20 bytes data) */
FUEL_GAUGE_DEVICE_NAME,
/** Chemistry (1 byte length + 4 bytes data) */
FUEL_GAUGE_DEVICE_CHEMISTRY,
/** Reserved to demark end of common fuel gauge properties */
FUEL_GAUGE_COMMON_COUNT,
/**
* Reserved to demark downstream custom properties - use this value as the actual value may
* change over future versions of this API
*/
FUEL_GAUGE_CUSTOM_BEGIN,
/** Reserved to demark end of valid enum properties */
FUEL_GAUGE_PROP_MAX = UINT16_MAX,
};
typedef uint16_t fuel_gauge_prop_t;
/** Property field to value/type union */
union fuel_gauge_prop_val {
/* Fields have the format: */
/* FUEL_GAUGE_PROPERTY_FIELD */
/* type property_field; */
/* Dynamic Battery Info */
/** FUEL_GAUGE_AVG_CURRENT */
int avg_current;
/** FUEL_GAUGE_CHARGE_CUTOFF */
bool cutoff;
/** FUEL_GAUGE_CURRENT */
int current;
/** FUEL_GAUGE_CYCLE_COUNT */
uint32_t cycle_count;
/** FUEL_GAUGE_FLAGS */
uint32_t flags;
/** FUEL_GAUGE_FULL_CHARGE_CAPACITY */
uint32_t full_charge_capacity;
/** FUEL_GAUGE_REMAINING_CAPACITY */
uint32_t remaining_capacity;
/** FUEL_GAUGE_RUNTIME_TO_EMPTY */
uint32_t runtime_to_empty;
/** FUEL_GAUGE_RUNTIME_TO_FULL */
uint32_t runtime_to_full;
/** FUEL_GAUGE_SBS_MFR_ACCESS */
uint16_t sbs_mfr_access_word;
/** FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE */
uint8_t absolute_state_of_charge;
/** FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE */
uint8_t relative_state_of_charge;
/** FUEL_GAUGE_TEMPERATURE */
uint16_t temperature;
/** FUEL_GAUGE_VOLTAGE */
int voltage;
/** FUEL_GAUGE_SBS_MODE */
uint16_t sbs_mode;
/** FUEL_GAUGE_CHARGE_CURRENT */
uint32_t chg_current;
/** FUEL_GAUGE_CHARGE_VOLTAGE */
uint32_t chg_voltage;
/** FUEL_GAUGE_STATUS */
uint16_t fg_status;
/** FUEL_GAUGE_DESIGN_CAPACITY */
uint16_t design_cap;
/** FUEL_GAUGE_DESIGN_VOLTAGE */
uint16_t design_volt;
/** FUEL_GAUGE_SBS_ATRATE */
int16_t sbs_at_rate;
/** FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL */
uint16_t sbs_at_rate_time_to_full;
/** FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY */
uint16_t sbs_at_rate_time_to_empty;
/** FUEL_GAUGE_SBS_ATRATE_OK */
bool sbs_at_rate_ok;
/** FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM */
uint16_t sbs_remaining_capacity_alarm;
/** FUEL_GAUGE_SBS_REMAINING_TIME_ALARM */
uint16_t sbs_remaining_time_alarm;
};
/**
* Data structures for reading SBS buffer properties
*/
#define SBS_GAUGE_MANUFACTURER_NAME_MAX_SIZE 20
#define SBS_GAUGE_DEVICE_NAME_MAX_SIZE 20
#define SBS_GAUGE_DEVICE_CHEMISTRY_MAX_SIZE 4
struct sbs_gauge_manufacturer_name {
uint8_t manufacturer_name_length;
char manufacturer_name[SBS_GAUGE_MANUFACTURER_NAME_MAX_SIZE];
} __packed;
struct sbs_gauge_device_name {
uint8_t device_name_length;
char device_name[SBS_GAUGE_DEVICE_NAME_MAX_SIZE];
} __packed;
struct sbs_gauge_device_chemistry {
uint8_t device_chemistry_length;
char device_chemistry[SBS_GAUGE_DEVICE_CHEMISTRY_MAX_SIZE];
} __packed;
/**
* @typedef fuel_gauge_get_property_t
* @brief Callback API for getting a fuel_gauge property.
*
* See fuel_gauge_get_property() for argument description
*/
typedef int (*fuel_gauge_get_property_t)(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val *val);
/**
* @typedef fuel_gauge_set_property_t
* @brief Callback API for setting a fuel_gauge property.
*
* See fuel_gauge_set_property() for argument description
*/
typedef int (*fuel_gauge_set_property_t)(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val val);
/**
* @typedef fuel_gauge_get_buffer_property_t
* @brief Callback API for getting a fuel_gauge buffer property.
*
* See fuel_gauge_get_buffer_property() for argument description
*/
typedef int (*fuel_gauge_get_buffer_property_t)(const struct device *dev,
fuel_gauge_prop_t prop_type,
void *dst, size_t dst_len);
/**
* @typedef fuel_gauge_battery_cutoff_t
* @brief Callback API for doing a battery cutoff.
*
* See fuel_gauge_battery_cutoff() for argument description
*/
typedef int (*fuel_gauge_battery_cutoff_t)(const struct device *dev);
/* Caching is entirely on the onus of the client */
__subsystem struct fuel_gauge_driver_api {
/**
* Note: Historically this API allowed drivers to implement a custom multi-get/set property
* function, this was added so drivers could potentially optimize batch read with their
* specific chip. However, it was removed because of no existing concrete case upstream.
* If this need is demonstrated, we can add this back in as an API field.
*/
fuel_gauge_get_property_t get_property;
fuel_gauge_set_property_t set_property;
fuel_gauge_get_buffer_property_t get_buffer_property;
fuel_gauge_battery_cutoff_t battery_cutoff;
};
/**
* @brief Fetch a battery fuel-gauge property
*
* @param dev Pointer to the battery fuel-gauge device
* @param prop Type of property to be fetched from device
* @param val pointer to a union fuel_gauge_prop_val where the property is read into from the
* fuel gauge device.
* @return 0 if successful, negative errno code if failure.
*/
__syscall int fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val *val);
static inline int z_impl_fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val *val)
{
const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
if (api->get_property == NULL) {
return -ENOSYS;
}
return api->get_property(dev, prop, val);
}
/**
* @brief Fetch multiple battery fuel-gauge properies. The default implementation is the same as
* calling fuel_gauge_get_prop() multiple times. A driver may implement the `get_properties` field
* of the fuel gauge driver APIs struct to override this implementation.
*
* @param dev Pointer to the battery fuel-gauge device
* @param props Array of the type of property to be fetched from device, each index corresponds
* to the same index of the vals input array.
* @param vals Pointer to array of union fuel_gauge_prop_val where the property is read into from
* the fuel gauge device. The vals array is not permuted.
* @param len number of properties in props & vals array
*
* @return 0 if successful, negative errno code of first failing property
*/
__syscall int fuel_gauge_get_props(const struct device *dev, fuel_gauge_prop_t *props,
union fuel_gauge_prop_val *vals, size_t len);
static inline int z_impl_fuel_gauge_get_props(const struct device *dev,
fuel_gauge_prop_t *props,
union fuel_gauge_prop_val *vals, size_t len)
{
const struct fuel_gauge_driver_api *api = dev->api;
for (int i = 0; i < len; i++) {
int ret = api->get_property(dev, props[i], vals + i);
if (ret) {
return ret;
}
}
return 0;
}
/**
* @brief Set a battery fuel-gauge property
*
* @param dev Pointer to the battery fuel-gauge device
* @param prop Type of property that's being set
* @param val Value to set associated prop property.
*
* @return 0 if successful, negative errno code of first failing property
*/
__syscall int fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val val);
static inline int z_impl_fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val val)
{
const struct fuel_gauge_driver_api *api = dev->api;
if (api->set_property == NULL) {
return -ENOSYS;
}
return api->set_property(dev, prop, val);
}
/**
* @brief Set a battery fuel-gauge property
*
* @param dev Pointer to the battery fuel-gauge device
* @param props Array of the type of property to be set, each index corresponds
* to the same index of the vals input array.
* @param vals Pointer to array of union fuel_gauge_prop_val where the property is written
* the fuel gauge device. The vals array is not permuted.
* @param len number of properties in props array
*
* @return return=0 if successful. Otherwise, return array index of failing property.
*/
__syscall int fuel_gauge_set_props(const struct device *dev, fuel_gauge_prop_t *props,
union fuel_gauge_prop_val *vals, size_t len);
static inline int z_impl_fuel_gauge_set_props(const struct device *dev,
fuel_gauge_prop_t *props,
union fuel_gauge_prop_val *vals, size_t len)
{
for (int i = 0; i < len; i++) {
int ret = fuel_gauge_set_prop(dev, props[i], vals[i]);
if (ret) {
return ret;
}
}
return 0;
}
/**
* @brief Fetch a battery fuel-gauge buffer property
*
* @param dev Pointer to the battery fuel-gauge device
* @param prop_type Type of property to be fetched from device
* @param dst byte array or struct that will hold the buffer data that is read from the fuel gauge
* @param dst_len the length of the destination array in bytes
*
* @return return=0 if successful, return < 0 if getting property failed, return 0 on success
*/
__syscall int fuel_gauge_get_buffer_prop(const struct device *dev, fuel_gauge_prop_t prop_type,
void *dst, size_t dst_len);
static inline int z_impl_fuel_gauge_get_buffer_prop(const struct device *dev,
fuel_gauge_prop_t prop_type,
void *dst, size_t dst_len)
{
const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
if (api->get_buffer_property == NULL) {
return -ENOSYS;
}
return api->get_buffer_property(dev, prop_type, dst, dst_len);
}
/**
* @brief Have fuel gauge cutoff its associated battery.
*
* @param dev Pointer to the battery fuel-gauge device
*
* @return return=0 if successful and battery cutoff is now in process, return < 0 if failed to do
* battery cutoff.
*/
__syscall int fuel_gauge_battery_cutoff(const struct device *dev);
static inline int z_impl_fuel_gauge_battery_cutoff(const struct device *dev)
{
const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
if (api->battery_cutoff == NULL) {
return -ENOSYS;
}
return api->battery_cutoff(dev);
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#include <zephyr/syscalls/fuel_gauge.h>
#endif /* ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_ */