Skip to content

iio: dac: Add AD5413 support #2786

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

BruceTsaoADI
Copy link

Summary

This PR adds initial support for the Analog Devices AD5413, a 14-bit single-channel DAC capable of voltage and current output.

Key changes

  • New driver: ad5413.c under drivers/iio/dac/
  • Devicetree binding: adi,ad5413.yaml under Documentation/devicetree/bindings/iio/dac/
  • Integrated with Kconfig and Makefile

Datasheet:

https://www.analog.com/media/en/technical-documentation/data-sheets/ad5413.pdf

PR Description

  • Please replace this comment with a summary of your changes, and add any context
    necessary to understand them. List any dependencies required for this change.
  • To check the checkboxes below, insert a 'x' between square brackets (without
    any space), or simply check them after publishing the PR.
  • If you changes include a breaking change, please specify dependent PRs in the
    description and try to push all related PRs simultaneously.

PR Type

  • Bug fix (a change that fixes an issue)
  • New feature (a change that adds new functionality)
  • Breaking change (a change that affects other repos or cause CIs to fail)

PR Checklist

  • I have conducted a self-review of my own code changes
  • I have tested the changes on the relevant hardware
  • I have updated the documentation outside this repo accordingly (if there is the case)

The AD5413 is a single-channel, 14-bit DAC with programmable current or
voltage output. It communicates via SPI at clock rates up to 50 MHz.

The output can be configured as either voltage or current and is available
on a single terminal.

Datasheet:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad5413.pdf

Signed-off-by: Bruce Tsao <[email protected]>
Copy link
Contributor

@gastmaier gastmaier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the warnings that caused the ci to exit with an error but were not logged

{
unsigned int tmp, tmparray[2], size;
const struct ad5413_range *range;
int *index, ret;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drivers/iio/dac/ad5413.c: In function 'ad5413_parse_dt':
::warning file=drivers/iio/dac/ad5413.c,line=590,col=14::gcc_fanalayzer: unused variable 'index' [-Wunused-variable]
590 | int *index, ret;
| ^~~~~

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve removed the unused index variable from the ad5413_parse_dt() signature so that only int ret remains. This eliminates the -Wunused-variable warning. Please let me know if you spot any other unused declarations.

Comment on lines +724 to +733
else
indio_dev->channels = ad5413_current_ch;

ret = ad5413_init(st);
if (ret < 0) {
dev_err(&spi->dev, "AD5413 init failed\n");
return ret;
}

return devm_iio_device_register(&st->spi->dev, indio_dev);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drivers/iio/dac/ad5413.c: In function 'ad5413_probe':
::warning file=drivers/iio/dac/ad5413.c,line=724,col=5::gcc_fanalayzer: this 'else' clause does not guard... [-Wmisleading-indentation]
724 | else
| ^~~~
drivers/iio/dac/ad5413.c:727:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'else'
727 | ret = ad5413_init(st);
| ^~~

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for spotting that. I’ve refactored the if/else block to use braces so the indentation matches the actual control flow. This removes the misleading indentation and eliminates the warning. Let me know if you’d like any further adjustments.

Comment on lines +24 to +26
enum:
- [-10500000, 10500000]
- [-12600000, 12600000]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum doesn't work like that. See other bindings that already have this same property for what works.

Suggested change
enum:
- [-10500000, 10500000]
- [-12600000, 12600000]
adi,range-microvolt:
description: Voltage output range specified as <minimum, maximum>
oneOf:
- items:
- const: -10500000
- const: 10500000
- items:
- const: -12600000
- const: 12600000

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve updated the adi,range-microvolt binding to use oneOf instead of enum.


adi,range-microamp:
description: Current output range <min, max> in microamps
enum:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Will also want to call out in the commit message why there is only one option here (and why adi,range-microvolt doesn't have a default: - the same reason - but it isn't obvious until later, so best to mention it before)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve updated adi,range-microamp to use oneOf with the single supported span (0–24 000 μA).

Comment on lines +34 to +35
description: |
Output digital slew control time in microseconds
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: |
Output digital slew control time in microseconds
description: Output digital slew control time in microseconds

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve changed the adi,slew-time-us property to use an inline description instead of a multi-line block.

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
- if:
required: [adi, range-microamp]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
required: [adi, range-microamp]
required: [ 'adi,range-microamp' ]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve updated the required array to quote the property name as ['adi,range-microamp'].

properties:
adi,range-microvolt: false
- if:
required: [adi, range-microvolt]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
required: [adi, range-microvolt]
required: [ 'adi,range-microvolt' ]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

/* 3) read slew-time(optional) */
ret = device_property_read_u32(&st->spi->dev,
"adi,slew-time-us", &tmp);
if (ret) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking all of the device_property_ returns in this function could be more strict. There are different errors for "property is missing" (-EINAL) and other error caused, e.g. by typos in the .dts file (e.g. a not enough items in the array).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the catch. I’ve updated the adi,slew-time-us handling so that:

-ENODATA and -EINVAL are treated as “property not provided” and default to 0

Any other negative return is treated as a real parsing error (logged via dev_err) and aborts probe

Please let me know if this covers all cases or if further tweaks are needed.


#define AD5413_DAC_CHAN(_chan_type) { \
.type = (_chan_type), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_RAW) | \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIO_CHAN_INFO_RAW is for sure separate, not shared_by_type. Since there aren't versions of this chip with more than one channel, it isn't clear if SCALE and OFFSET should also be separate, so could go either way on those.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pointing that out. I’ve removed IIO_CHAN_INFO_RAW from info_mask_shared_by_type and added it to info_mask_separate to ensure RAW is treated as a separate attribute. SCALE and OFFSET remain in info_mask_shared_by_type since this device only has one channel. Please let me know if you’d prefer SCALE and OFFSET to be marked separate as well.

int *index, ret;

/* 1) voltage */
ret = device_property_read_u32_array(&st->spi->dev,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will allow the +/- 12.6 range to be given in the devicetree but set up the chip for +/-10.5V, but OVRNG_EN isn't implemented yet. So we should not allow that or now or implement OVRNG_EN.

It also wouldn't hurt to check the current values as well (even if there is only one option, someone might try to put something else in the .dts file)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for catching that. I’ve made the following updates:

Voltage range: The DT binding and driver now only allow ±10.5 V. Any attempt to use ±12.6 V is rejected with -EINVAL until we implement the OVRNG_EN bit.

Current range: Added explicit validation so that adi,range-microamp must be exactly 0–24 000 µA; anything else also returns -EINVAL.

With these checks in place, we prevent the chip from being configured for unsupported ranges. OVRNG_EN support can be added in a follow-up patch once fully tested.


struct ad5413_range {
int reg;
int min;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upstream prefers units on macros and variables, e.g. min_uv here.

Same applies throughout the driver. (It would especially help to make the raw_read function easier to understand)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion. I’ve renamed all range struct members and related macros to include explicit unit suffixes (e.g. min_uv/max_uv for microvolt ranges), which should improve readability and prevent confusion. Please let me know if any other identifiers need unit annotations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants