Skip to content

Commit

Permalink
fuel_gauge: Repl property struct w/ union
Browse files Browse the repository at this point in the history
Based on review of the similar charger driver API, it's been demonstrated
from the community that embedding a per value property type when fetching
properties. Separating off the property types from the property values
themselves also allow an array of property types to declared as static
const.

Break up fuel_gauge_property struct into a fuel_gauge_prop_val union and a
fuel_gauge_prop_t property type as inputs into fuel gauge API functions.

(cherry picked from commit 12cbfcf)

Original-Signed-off-by: Aaron Massey <aaronmassey@google.com>
GitOrigin-RevId: 12cbfcf
Change-Id: I8ec43bb6c2f91e5dcf76377e6e47ab862de8a8b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/4896613
Reviewed-by: Al Semjonovs <asemjonovs@google.com>
Tested-by: ChromeOS Prod (Robot) <chromeos-ci-prod@chromeos-bot.iam.gserviceaccount.com>
Tested-by: Al Semjonovs <asemjonovs@google.com>
Tested-by: Keith Short <keithshort@chromium.org>
Commit-Queue: Al Semjonovs <asemjonovs@google.com>
  • Loading branch information
aaronemassey authored and Chromeos LUCI committed Sep 27, 2023
1 parent b76b10c commit 3d24e41
Show file tree
Hide file tree
Showing 10 changed files with 491 additions and 680 deletions.
8 changes: 5 additions & 3 deletions doc/hardware/peripherals/fuel_gauge.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ Fundamentally, a property is a quantity that a fuel gauge device can measure.
Fuel gauges typically support multiple properties, such as temperature readings of the battery-pack
or present-time current/voltage.

Properties are fetched one at a time using a client allocated :c:struct:`fuel_gauge_property` or
fetched all at once using a client allocated array of :c:struct:`fuel_gauge_property`. Each
:c:struct:`fuel_gauge_property` is populated by values according to its `property_type` field.
Properties are fetched by the client one at a time using :c:func:`fuel_gauge_get_prop`, or fetched
in a batch using :c:func:`fuel_gauge_get_props`.

Properties are set by the client one at a time using :c:func:`fuel_gauge_set_prop`, or set in a
batch using :c:func:`fuel_gauge_set_props`.

Battery Cutoff
==============
Expand Down
95 changes: 48 additions & 47 deletions drivers/fuel_gauge/bq27z746/bq27z746.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,84 +109,85 @@ static int bq27z746_read_mac(const struct device *dev, uint16_t cmd, uint8_t *da
return ret;
}

static int bq27z746_get_prop(const struct device *dev, struct fuel_gauge_property *prop)
static int bq27z746_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val *val)
{
int rc = 0;
uint16_t val = 0;
uint16_t tmp_val = 0;

/*
* Possibly negative values must be cast from uint16 to int16 first to
* then correctly end up in the wider datatypes of `prop`.
*/

switch (prop->property_type) {
switch (prop) {
case FUEL_GAUGE_AVG_CURRENT:
rc = bq27z746_read16(dev, BQ27Z746_AVERAGECURRENT, &val);
prop->value.avg_current = (int16_t)val * 1000;
rc = bq27z746_read16(dev, BQ27Z746_AVERAGECURRENT, &tmp_val);
val->avg_current = (int16_t)tmp_val * 1000;
break;
case FUEL_GAUGE_CYCLE_COUNT:
rc = bq27z746_read16(dev, BQ27Z746_CYCLECOUNT, &val);
prop->value.cycle_count = val * 100;
rc = bq27z746_read16(dev, BQ27Z746_CYCLECOUNT, &tmp_val);
val->cycle_count = tmp_val * 100;
break;
case FUEL_GAUGE_CURRENT:
rc = bq27z746_read16(dev, BQ27Z746_CURRENT, &val);
prop->value.current = (int16_t)val * 1000;
rc = bq27z746_read16(dev, BQ27Z746_CURRENT, &tmp_val);
val->current = (int16_t)tmp_val * 1000;
break;
case FUEL_GAUGE_FULL_CHARGE_CAPACITY:
rc = bq27z746_read16(dev, BQ27Z746_FULLCHARGECAPACITY, &val);
prop->value.full_charge_capacity = val * 1000;
rc = bq27z746_read16(dev, BQ27Z746_FULLCHARGECAPACITY, &tmp_val);
val->full_charge_capacity = tmp_val * 1000;
break;
case FUEL_GAUGE_REMAINING_CAPACITY:
rc = bq27z746_read16(dev, BQ27Z746_REMAININGCAPACITY, &val);
prop->value.remaining_capacity = val * 1000;
rc = bq27z746_read16(dev, BQ27Z746_REMAININGCAPACITY, &tmp_val);
val->remaining_capacity = tmp_val * 1000;
break;
case FUEL_GAUGE_RUNTIME_TO_EMPTY:
rc = bq27z746_read16(dev, BQ27Z746_AVERAGETIMETOEMPTY, &val);
prop->value.runtime_to_empty = val;
rc = bq27z746_read16(dev, BQ27Z746_AVERAGETIMETOEMPTY, &tmp_val);
val->runtime_to_empty = tmp_val;
break;
case FUEL_GAUGE_RUNTIME_TO_FULL:
rc = bq27z746_read16(dev, BQ27Z746_AVERAGETIMETOFULL, &val);
prop->value.runtime_to_full = val;
rc = bq27z746_read16(dev, BQ27Z746_AVERAGETIMETOFULL, &tmp_val);
val->runtime_to_full = tmp_val;
break;
case FUEL_GAUGE_SBS_MFR_ACCESS:
rc = bq27z746_read16(dev, BQ27Z746_MANUFACTURERACCESS, &val);
prop->value.sbs_mfr_access_word = val;
rc = bq27z746_read16(dev, BQ27Z746_MANUFACTURERACCESS, &tmp_val);
val->sbs_mfr_access_word = tmp_val;
break;
case FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE:
rc = bq27z746_read16(dev, BQ27Z746_RELATIVESTATEOFCHARGE, &val);
prop->value.relative_state_of_charge = val;
rc = bq27z746_read16(dev, BQ27Z746_RELATIVESTATEOFCHARGE, &tmp_val);
val->relative_state_of_charge = tmp_val;
break;
case FUEL_GAUGE_TEMPERATURE:
rc = bq27z746_read16(dev, BQ27Z746_TEMPERATURE, &val);
prop->value.temperature = val;
rc = bq27z746_read16(dev, BQ27Z746_TEMPERATURE, &tmp_val);
val->temperature = tmp_val;
break;
case FUEL_GAUGE_VOLTAGE:
rc = bq27z746_read16(dev, BQ27Z746_VOLTAGE, &val);
prop->value.voltage = val * 1000;
rc = bq27z746_read16(dev, BQ27Z746_VOLTAGE, &tmp_val);
val->voltage = tmp_val * 1000;
break;
case FUEL_GAUGE_SBS_ATRATE:
rc = bq27z746_read16(dev, BQ27Z746_ATRATE, &val);
prop->value.sbs_at_rate = (int16_t)val;
rc = bq27z746_read16(dev, BQ27Z746_ATRATE, &tmp_val);
val->sbs_at_rate = (int16_t)tmp_val;
break;
case FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY:
rc = bq27z746_read16(dev, BQ27Z746_ATRATETIMETOEMPTY, &val);
prop->value.sbs_at_rate_time_to_empty = val;
rc = bq27z746_read16(dev, BQ27Z746_ATRATETIMETOEMPTY, &tmp_val);
val->sbs_at_rate_time_to_empty = tmp_val;
break;
case FUEL_GAUGE_CHARGE_VOLTAGE:
rc = bq27z746_read16(dev, BQ27Z746_CHARGINGVOLTAGE, &val);
prop->value.chg_voltage = val;
rc = bq27z746_read16(dev, BQ27Z746_CHARGINGVOLTAGE, &tmp_val);
val->chg_voltage = tmp_val;
break;
case FUEL_GAUGE_CHARGE_CURRENT:
rc = bq27z746_read16(dev, BQ27Z746_CHARGINGCURRENT, &val);
prop->value.chg_current = val;
rc = bq27z746_read16(dev, BQ27Z746_CHARGINGCURRENT, &tmp_val);
val->chg_current = tmp_val;
break;
case FUEL_GAUGE_STATUS:
rc = bq27z746_read16(dev, BQ27Z746_BATTERYSTATUS, &val);
prop->value.fg_status = val;
rc = bq27z746_read16(dev, BQ27Z746_BATTERYSTATUS, &tmp_val);
val->fg_status = tmp_val;
break;
case FUEL_GAUGE_DESIGN_CAPACITY:
rc = bq27z746_read16(dev, BQ27Z746_DESIGNCAPACITY, &val);
prop->value.design_cap = val;
rc = bq27z746_read16(dev, BQ27Z746_DESIGNCAPACITY, &tmp_val);
val->design_cap = tmp_val;
break;
default:
rc = -ENOTSUP;
Expand All @@ -196,12 +197,12 @@ static int bq27z746_get_prop(const struct device *dev, struct fuel_gauge_propert
}

static int bq27z746_get_buffer_prop(const struct device *dev,
struct fuel_gauge_buffer_property *prop, void *dst,
fuel_gauge_prop_t property_type, void *dst,
size_t dst_len)
{
int rc = 0;

switch (prop->property_type) {
switch (property_type) {
case FUEL_GAUGE_MANUFACTURER_NAME:
if (dst_len == sizeof(struct sbs_gauge_manufacturer_name)) {
rc = bq27z746_read_mac(dev, BQ27Z746_MAC_CMD_MANUFACTURER_NAME,
Expand Down Expand Up @@ -233,20 +234,20 @@ static int bq27z746_get_buffer_prop(const struct device *dev,
return rc;
}

static int bq27z746_set_prop(const struct device *dev, struct fuel_gauge_property *prop)
static int bq27z746_set_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val val)
{
int rc = 0;
uint16_t val = 0;
uint16_t tmp_val = 0;

switch (prop->property_type) {
switch (prop) {
case FUEL_GAUGE_SBS_MFR_ACCESS:
rc = bq27z746_write16(dev, BQ27Z746_MANUFACTURERACCESS,
prop->value.sbs_mfr_access_word);
prop->value.sbs_mfr_access_word = val;
rc = bq27z746_write16(dev, BQ27Z746_MANUFACTURERACCESS, val.sbs_mfr_access_word);
val.sbs_mfr_access_word = tmp_val;
break;
case FUEL_GAUGE_SBS_ATRATE:
rc = bq27z746_write16(dev, BQ27Z746_ATRATE, prop->value.sbs_at_rate);
prop->value.sbs_at_rate = val;
rc = bq27z746_write16(dev, BQ27Z746_ATRATE, val.sbs_at_rate);
val.sbs_at_rate = tmp_val;
break;
default:
rc = -ENOTSUP;
Expand Down
67 changes: 29 additions & 38 deletions drivers/fuel_gauge/fuel_gauge_syscall_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,95 +8,86 @@
#include <zephyr/syscall_handler.h>
#include <zephyr/drivers/fuel_gauge.h>

static inline int z_vrfy_fuel_gauge_get_prop(const struct device *dev,
struct fuel_gauge_property *prop)
static inline int z_vrfy_fuel_gauge_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val *val)
{
struct fuel_gauge_property k_prop;
union fuel_gauge_prop_val k_val;

Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property));

Z_OOPS(z_user_from_copy(&k_prop, prop, sizeof(struct fuel_gauge_property)));
Z_OOPS(z_user_from_copy(&k_val, val, sizeof(union fuel_gauge_prop_val)));

int ret = z_impl_fuel_gauge_get_prop(dev, &k_prop);
int ret = z_impl_fuel_gauge_get_prop(dev, prop, &k_val);

Z_OOPS(z_user_to_copy(prop, &k_prop, sizeof(struct fuel_gauge_property)));
Z_OOPS(z_user_to_copy(val, &k_val, sizeof(union fuel_gauge_prop_val)));

return ret;
}

#include <syscalls/fuel_gauge_get_prop_mrsh.c>

static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev,
struct fuel_gauge_property *props, size_t props_len)
static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev, fuel_gauge_prop_t *props,
union fuel_gauge_prop_val *vals, size_t len)
{
struct fuel_gauge_property k_props[props_len];
union fuel_gauge_prop_val k_vals[len];
fuel_gauge_prop_t k_props[len];

Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property));

Z_OOPS(z_user_from_copy(k_props, props, props_len * sizeof(struct fuel_gauge_property)));
Z_OOPS(z_user_from_copy(k_vals, vals, len * sizeof(union fuel_gauge_prop_val)));
Z_OOPS(z_user_from_copy(k_props, props, len * sizeof(fuel_gauge_prop_t)));

int ret = z_impl_fuel_gauge_get_props(dev, k_props, props_len);
int ret = z_impl_fuel_gauge_get_props(dev, k_props, k_vals, len);

Z_OOPS(z_user_to_copy(props, k_props, props_len * sizeof(struct fuel_gauge_property)));
Z_OOPS(z_user_to_copy(vals, k_vals, len * sizeof(union fuel_gauge_prop_val)));

return ret;
}

#include <syscalls/fuel_gauge_get_props_mrsh.c>

static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev,
struct fuel_gauge_property *prop)
static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val val)
{
struct fuel_gauge_property k_prop;

Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, set_property));

Z_OOPS(z_user_from_copy(&k_prop, prop, sizeof(struct fuel_gauge_property)));

int ret = z_impl_fuel_gauge_set_prop(dev, &k_prop);

Z_OOPS(z_user_to_copy(prop, &k_prop, sizeof(struct fuel_gauge_property)));
int ret = z_impl_fuel_gauge_set_prop(dev, prop, val);

return ret;
}

#include <syscalls/fuel_gauge_set_prop_mrsh.c>

static inline int z_vrfy_fuel_gauge_set_props(const struct device *dev,
struct fuel_gauge_property *props, size_t props_len)
static inline int z_vrfy_fuel_gauge_set_props(const struct device *dev, fuel_gauge_prop_t *props,
union fuel_gauge_prop_val *vals, size_t len)
{
struct fuel_gauge_property k_props[props_len];
union fuel_gauge_prop_val k_vals[len];
fuel_gauge_prop_t k_props[len];

Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, set_property));

Z_OOPS(z_user_from_copy(k_props, props, props_len * sizeof(struct fuel_gauge_property)));
Z_OOPS(z_user_from_copy(k_vals, vals, len * sizeof(union fuel_gauge_prop_val)));
Z_OOPS(z_user_from_copy(k_props, props, len * sizeof(fuel_gauge_prop_t)));

int ret = z_impl_fuel_gauge_set_props(dev, k_props, props_len);
int ret = z_impl_fuel_gauge_set_props(dev, k_props, k_vals, len);

Z_OOPS(z_user_to_copy(props, k_props, props_len * sizeof(struct fuel_gauge_property)));
/* We only copy back vals because props will never be modified */
Z_OOPS(z_user_to_copy(vals, k_vals, len * sizeof(union fuel_gauge_prop_val)));

return ret;
}

#include <syscalls/fuel_gauge_set_props_mrsh.c>

static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev,
struct fuel_gauge_buffer_property *prop,
void *dst, size_t dst_len)
fuel_gauge_prop_t prop, void *dst,
size_t dst_len)
{
struct fuel_gauge_buffer_property k_prop;

Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_buffer_property));

Z_OOPS(z_user_from_copy(&k_prop, prop,
sizeof(struct fuel_gauge_buffer_property)));

Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, dst_len));

int ret = z_impl_fuel_gauge_get_buffer_prop(dev, &k_prop, dst, dst_len);

Z_OOPS(z_user_to_copy(prop, &k_prop,
sizeof(struct fuel_gauge_buffer_property)));
int ret = z_impl_fuel_gauge_get_buffer_prop(dev, prop, dst, dst_len);

return ret;
}
Expand Down
18 changes: 10 additions & 8 deletions drivers/fuel_gauge/max17048/max17048.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,23 +175,24 @@ static int max17048_init(const struct device *dev)
/**
* Get a single property from the fuel gauge
*/
static int max17048_get_single_prop_impl(const struct device *dev, struct fuel_gauge_property *prop)
static int max17048_get_single_prop_impl(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val *val)
{
struct max17048_data *data = dev->data;
int rc = 0;

switch (prop->property_type) {
switch (prop) {
case FUEL_GAUGE_RUNTIME_TO_EMPTY:
prop->value.runtime_to_empty = data->time_to_empty;
val->runtime_to_empty = data->time_to_empty;
break;
case FUEL_GAUGE_RUNTIME_TO_FULL:
prop->value.runtime_to_full = data->time_to_full;
val->runtime_to_full = data->time_to_full;
break;
case FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE:
prop->value.relative_state_of_charge = data->charge;
val->relative_state_of_charge = data->charge;
break;
case FUEL_GAUGE_VOLTAGE:
prop->value.voltage = data->voltage;
val->voltage = data->voltage;
break;
default:
rc = -ENOTSUP;
Expand All @@ -203,7 +204,8 @@ static int max17048_get_single_prop_impl(const struct device *dev, struct fuel_g
/**
* Get properties from the fuel gauge
*/
static int max17048_get_prop(const struct device *dev, struct fuel_gauge_property *prop)
static int max17048_get_prop(const struct device *dev, fuel_gauge_prop_t prop,
union fuel_gauge_prop_val *val)
{
struct max17048_data *data = dev->data;
int rc = max17048_percent(dev, &data->charge);
Expand Down Expand Up @@ -273,7 +275,7 @@ static int max17048_get_prop(const struct device *dev, struct fuel_gauge_propert
data->time_to_empty = 0;
}

ret = max17048_get_single_prop_impl(dev, prop);
ret = max17048_get_single_prop_impl(dev, prop, val);

return ret;
}
Expand Down
Loading

0 comments on commit 3d24e41

Please sign in to comment.