-
Notifications
You must be signed in to change notification settings - Fork 7.7k
drivers: fuelguage: Add ADI LTC2959 driver #90356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
drivers: fuelguage: Add ADI LTC2959 driver #90356
Conversation
Signed-off-by: Nathan <natelostintimeandspace@gmail.com>
Hello @LostinTimeandspaceYT, and thank you very much for your first pull request to the Zephyr project! |
Signed-off-by: Nathan <natelostintimeandspace@gmail.com>
Signed-off-by: Nathan <natelostintimeandspace@gmail.com>
@@ -0,0 +1,3 @@ | |||
zephyr_library() | |||
zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) | |||
zephyr_library_sources(ltc2959.c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the driver itself is missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My apologies. I was pushing the driver itself in a separate commit.
Signed-off-by: Nathan <natelostintimeandspace@gmail.com>
Signed-off-by: Nathan <natelostintimeandspace@gmail.com>
Signed-off-by: Nathan Winslow <natelostintimeandspace@gmail.com>
|
Thanks for your contribution. Please refactor your commit title and body so that they adhere to Pull Request Guidelines. See these examples: You should also merge your commits into a single commit to retain bisectability as described in PR Requirements Do not forget to address the compliance failures as well: https://github.com/zephyrproject-rtos/zephyr/actions/runs/15276958086/job/42967094398?pr=90356 |
config FUEL_GAUGE_LTC2959_RSENSE_MOHMS | ||
|
||
depends on FUEL_GAUGE_LTC2959 | ||
int "Sense resistor value in milliohms" | ||
default 80 | ||
help | ||
Set the value of the RSENSE resistor in milliohms. | ||
This is used to calculate the current and charge resolution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a hardware parameter, so I suggest converting it into a devicetree property. See https://docs.zephyrproject.org/latest/build/dts/dt-vs-kconfig.html.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I will move this into the binding.
config FUEL_GAUGE_LTC2959 | ||
|
||
depends on DT_HAS_ADI_LTC2959_ENABLED | ||
bool "LTC2959 Fuel Gauge" | ||
default y | ||
select I2C | ||
help | ||
Enable the LTC2959 fuel gauge driver from Analog Devices. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config FUEL_GAUGE_LTC2959 | |
depends on DT_HAS_ADI_LTC2959_ENABLED | |
bool "LTC2959 Fuel Gauge" | |
default y | |
select I2C | |
help | |
Enable the LTC2959 fuel gauge driver from Analog Devices. | |
config FUEL_GAUGE_LTC2959 | |
depends on DT_HAS_ADI_LTC2959_ENABLED | |
bool "LTC2959 Fuel Gauge" | |
default y | |
select I2C | |
help | |
Enable the LTC2959 fuel gauge driver from Analog Devices. |
const struct ltc2959_config *cfg = dev->config; | ||
mask &= LTC2959_CC_WRITABLE_MASK; | ||
mask |= LTC2959_CC_RESERVED_VALUE; | ||
LOG_INF("setting cc to: 0x%02X", mask); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG_INF("setting cc to: 0x%02X", mask); | |
LOG_DBG("setting cc to: 0x%02X", mask); |
int ret = ltc2959_read16(dev, reg, &raw); | ||
|
||
if (ret < 0) { | ||
LOG_ERR("ERROR: %i", ret); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could do with a verbose error message here.
#if 0 | ||
static int ltc2959_get_props(const struct device *dev, | ||
fuel_gauge_prop_t *props, | ||
union fuel_gauge_prop_val *vals, | ||
size_t len) | ||
{ | ||
|
||
int ret; | ||
for (size_t i = 0; i < len; ++i) { | ||
ret = ltc2959_get_prop(dev, props[i], &vals[i]); | ||
if (ret < 0) { | ||
return ret; | ||
} | ||
} | ||
return 0; | ||
|
||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not introduce dead code.
#if 0 | |
static int ltc2959_get_props(const struct device *dev, | |
fuel_gauge_prop_t *props, | |
union fuel_gauge_prop_val *vals, | |
size_t len) | |
{ | |
int ret; | |
for (size_t i = 0; i < len; ++i) { | |
ret = ltc2959_get_prop(dev, props[i], &vals[i]); | |
if (ret < 0) { | |
return ret; | |
} | |
} | |
return 0; | |
} | |
#endif |
label: | ||
required: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do you use this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was being used in test code to verify the binding. I will remove this property
alert-gpios: | ||
type: phandle-array | ||
description: | | ||
Optional GPIO used for ALERT output. The LTC2959 pulls this pin low | ||
when thresholds are crossed or charge events occur. Typically wired | ||
to a host interrupt-capable GPIO pin. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not seem to be used anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ttmut I will create a custom property to access the state of this pin.
Signed-off-by: Nathan <natelostintimeandspace@gmail.com>
|
Thank you @ttmut for reviewing this PR. I will have time later this week to work on the needed changes and consolidate the commits as per the guidelines. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, thanks for your contribution and overall it looks well done!
I also looked inside the datasheet and as far as I see you implemented every necessary/interesting feature from the IC. Interestingly, the IC does not provide a relative state of charge in percent, but it is what it is.
Please also add an e.g. ltc2959-emulation
, for example emul_lc709203f.c, emul_max17048, or emul_bq27z746.c and also a test (look here), because this helps a lot to avoid possible future breaking changes and further increase the test coverage and quality of Zephyr.
/* Used when ACR is controlled via firmware */ | ||
#define LTC2959_ACR_CLR (0xFFFFFFFF) | ||
|
||
#ifdef CONFIG_FUEL_GAUGE_LTC2959_RSENSE_MOHMS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be done via Devicetree as stated here can be removed here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, these are helpful examples. I will add an emul
and ztest.
/* LTC2959 Register Map — from datasheet (Rev A) */ | ||
|
||
/* Status and Control */ | ||
#define LTC2959_REG_STATUS (0x00) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to put all registers in an enum, see here for example.
Furthermore, except the enum ltc2959_custom_props
and the registers, everything else (the constant values even including the struct ltc2959_config
, etc.) can/should be moved to the ltc2959.c, because there is no need to have it in the public interface.
|
||
int ret = i2c_burst_read_dt(&cfg->i2c, reg, buf, sizeof(buf)); | ||
|
||
if (ret < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (ret < 0) { | |
if (ret) { |
but both ways are valid
case LTC2959_GPIO_MODE_ALERT: | ||
case LTC2959_GPIO_MODE_CHGCOMP: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case LTC2959_GPIO_MODE_ALERT: | |
case LTC2959_GPIO_MODE_CHGCOMP: |
If they are doing nothing, the default:
branch is enough.
FUEL_GAUGE_VOLTAGE_HIGH_THRESHOLD, | ||
FUEL_GAUGE_VOLTAGE_LOW_THRESHOLD, | ||
FUEL_GAUGE_CURRENT_HIGH_THRESHOLD, | ||
FUEL_GAUGE_CURRENT_LOW_THRESHOLD, | ||
FUEL_GAUGE_TEMPERATURE_HIGH_THRESHOLD, | ||
FUEL_GAUGE_TEMPERATURE_LOW_THRESHOLD, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For FUEL_GAUGE_VOLTAGE_LOW_THRESHOLD
the FUEL_GAUGE_LOW_VOLTAGE_ALARM
property already exists.
But nevertheless, I think it is valid to add the other 5 properties to the fuel_gauge.h
interface, for me it seems legit to add them, because if we already have a low-voltage-alarm why not have a high-voltage-alarm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I elected not to use FUEL_GAUGE_LOW_VOLTAGE_ALARM
as that reports a percentage of charge. The purpose of these properties is for configuring bounds to trigger a fault in the status register. I am not sure how other ICs of this ilk operate, but I agree @DBS06, I think adding them would make sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LostinTimeandspaceYT FUEL_GAUGE_LOW_VOLTAGE_ALARM
is described in fuel_gauge.h
as /** Low Cell Voltage Alarm (uV)*/
so it does not "reports a percentage of charge", I think you mismatch that with FUEL_GAUGE_STATE_OF_CHARGE_ALARM
which is described as /** Remaining state of charge alarm (percent, 0-100) */
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DBS06 You're right I did, classic off-by-1 😅
I could change the current FUEL_GAUGE_LOW_XXXX_THRESHOLD
to FUEL_GAUGE_LOW_XXX_ALARM
to have the property names be consistent with the current API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could change the current FUEL_GAUGE_LOW_XXXX_THRESHOLD to FUEL_GAUGE_LOW_XXX_ALARM to have the property names be consistent with the current API.
Exactly what I meant! You can keep the register names as it is and just adopt the property names (they are more or less generic names).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started work on this driver in a project on v4.1.0
and it looks like the FUEL_GAUGE_LOW_VOLTAGE_ALARM
property was added after that release. I noticed the discrepancy when attempting to build in that project. I Apologize for the confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to apologize! That's why code reviews are for.
Yes, I added it after my last PR #90310, which went bigger than originally expected 🤔
Just a minor hint, if you are adding additional properties do that in a separate commit (look at the commits from here #90310) and it should be the first one, as far as I see you can squash all other currently existing commits into one commit. If you add a test for your driver do that in another commit. So basically in the end you have three commits which will be pushed in the main branch.
I hope this helps!
This driver integrates with Zephyr’s fuel gauge subsystem to provide access to telemetry data such as voltage, current, temperature, and accumulated charge.
Tested on custom hardware with known RSENSE configuration and verified against datasheet behavior.
Signed-off-by: Nathan Winslow natelostintimeandspace@gmail.com