Skip to content
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

ad5791 offload #2616

Merged
merged 12 commits into from
Dec 12, 2024
Merged

ad5791 offload #2616

merged 12 commits into from
Dec 12, 2024

Conversation

ahaslam2
Copy link
Collaborator

spi offload support for ad57xx dac

This adds offload support for the ad57xx dac to be able to send samples up to 1MSPS.

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)

@ahaslam2 ahaslam2 force-pushed the axelh/ad5791_offload branch 5 times, most recently from 802e9b1 to 3976d47 Compare October 15, 2024 15:55
@ahaslam2 ahaslam2 changed the title Axelh/ad5791 offload ad5791 offload Oct 15, 2024
@ahaslam2 ahaslam2 force-pushed the axelh/ad5791_offload branch 2 times, most recently from 03d271e to 65e5a18 Compare October 16, 2024 10:14
@ahaslam2 ahaslam2 marked this pull request as ready for review October 16, 2024 10:16
@ahaslam2 ahaslam2 requested a review from dlech October 16, 2024 10:17
Copy link
Collaborator

@nunojsa nunojsa left a comment

Choose a reason for hiding this comment

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

Here it goes my review. Note that I'm expecting some stuff to be sent upstream (like gpio reset)... Also it seems this driver could use a proper refactor if you are willing to do that 😄

st->gpio_ldac = devm_gpiod_get_optional(&spi->dev, "ldac",
GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_ldac))
return PTR_ERR(st->gpio_ldac);
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the intent of the above two gpio's? I would say, if we're not using them now, don't bother in adding them. Still ok to leave them in the bindings though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

they are actually on the eval board and if i dont drive them they are set as input. we need to make sure they are on the right state: CLR high and LDAC low (datasheet table9 p21) for the output to be set according to the register value when we write on spi xfer. I think we need to keep them.

st->gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_reset))
return PTR_ERR(st->gpio_reset);
Copy link
Collaborator

Choose a reason for hiding this comment

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

The above makes sense to have already. But do a reset in case we have it. Typical pattern is:

gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset",  GPIOD_OUT_HIGH);
if (IS_ERR(gpio_reset))
    return PTR_ERR(gpio_reset);

if (gpio_reset) {
    // typically there's some time we need to wait for the reset to happen
    fseep(x);
    // get it out of reset
    gpiod_set_value_cansleep(gpio_reset, 0);
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok

st->pwr_down = pwr_down;

ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl);
ret = __ad5791_dac_powerdown(indio_dev, pwr_down);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated change. Not disagreeing with it but should be in a separate patch. If you want to take it one step further, it even seems that some proper locking is missing... Moreover, we should set st->pwr_down after we actually do ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

i will drop this change and only check the power status in pre-enable. as you suggested below.


if (spi_engine_ex_offload_supported(spi)) {
indio_dev->channels =
&ad5791_channels[spi_get_device_id(spi)->driver_data];
Copy link
Collaborator

@nunojsa nunojsa Oct 16, 2024

Choose a reason for hiding this comment

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

The above could also be an opportunity for a nice cleanup. Adding a chip_info structure and actual OF support. Thus getting rid of the id enum

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok

struct ad5791_state *st = iio_priv(indio_dev);
int ret;

ret = __ad5791_dac_powerdown(indio_dev, false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I see now it's related but see below...

pwm_disable(st->cnv_trigger);
spi_bus_unlock(st->spi->master);

return __ad5791_dac_powerdown(indio_dev, true);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Any reason to assume we want to powerdown the DAC? Since it's a user control I would rather check it and return error or something in ad5791_buffer_preenable() in case it's in a powerdown state. This would also mean that we can't power it down while in buffer mode. Thus, using iio_device_claim_direct_mode()

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok.

int ret;

if (!st->cnv_trigger)
return -ENODEV;
Copy link
Collaborator

Choose a reason for hiding this comment

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

AFAICT, this is only available for offload support and cnv_trigger is mandatory (otherwise we fail to probe). So, seems like a redundant check.

Copy link
Collaborator

@dlech dlech left a comment

Choose a reason for hiding this comment

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

A couple more suggestions for upstream "cleanup":

  • Use devm_regulator_get_enable_read_voltage() to simplify the regulator code.
  • Drop the driver remove callback by using more devm_.

@ahaslam2 ahaslam2 force-pushed the axelh/ad5791_offload branch from 65e5a18 to 5be52c8 Compare October 21, 2024 13:46
@ahaslam2
Copy link
Collaborator Author

changes in V2:

implement new suggested driver simplifications:

  • Include chip_info in device match tables / remove chip id enum
  • use devm_regulator_get_enable_read_voltage on probe.

Fixes related to comments:

  • drop pwm DT binding
  • use devm_spi_optimize_message
  • dont power_up/down on enable
  • remove redundant trigger check
  • us hw pin reset if available
  • factor out offload setup from probe.
  • rebase after de10nano DT changes from uwe.

@@ -430,30 +412,9 @@ static int ad5791_probe(struct spi_device *spi)
indio_dev->name = st->chip_info->name;
ret = iio_device_register(indio_dev);
if (ret)
goto error_disable_reg_neg;
return dev_err_probe(&spi->dev, ret, "unable to register iio device\n");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Most drivers will just return devm_iio_device_register() directly, so don't usually have the dev_err_probe() here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok

@ahaslam2 ahaslam2 force-pushed the axelh/ad5791_offload branch 2 times, most recently from 0c0d193 to 9c53b59 Compare October 22, 2024 13:47
@ahaslam2
Copy link
Collaborator Author

changes in V3:

  • add patch to remove altr,gpio-bank-width in dt nodes
  • remove adi,channels node
  • fix macro style.
  • use fsleep
  • remove spi_set_drvdata
  • use devm_iio_device_register and delete remove callback.

static int ad5791_get_sampling_freq(struct ad5791_state *st)
{
return DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC,
pwm_get_period(st->cnv_trigger));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we still want DIV_ROUND_CLOSEST_ULL()? @ukleinek seemed to have doubts about it...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

i missed to address that. in fact is the same on the 400x driver. i guess we need to change both.


st->spi_transfer.len = 4;
st->spi_transfer.bits_per_word = 24;
st->spi_transfer.tx_buf = (void *)-1; /* steaming tx */
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: we could have a better comment for why we have to do this (ugly) hack

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok

if (st->pwr_down)
return -EINVAL;

ret = pwm_enable(st->cnv_trigger);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks like we have an extra space?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes. will remove.

Comment on lines 487 to 488
return devm_add_action_or_reset(&spi->dev, ad5791_pwm_disable,
st->cnv_trigger);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm also wondering about the devm action. AFAICT, you're not enabling the PWM in __ad5791_set_sampling_freq() so this looks unbalanced... I guess this is not really a problem but also looks unnecessary.

@ahaslam2
Copy link
Collaborator Author

ahaslam2 commented Nov 5, 2024

  • Use 3 arguments for pwm node in dts

I don't see this change in arch/arm/boot/dts/socfpga_arria10_socdk_adrv9025.dts.

the device tree is actually: arch/arm/boot/dts/socfpga_cyclone5_de10_nano_ad57xx.dts
but i see what you mean, somehow this change did not get included in my push. will fix

if (ret) {
ad5791_pwm_disable(st->cnv_trigger);
return ret;
}
Copy link
Collaborator

@nunojsa nunojsa Nov 5, 2024

Choose a reason for hiding this comment

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

Somehow this did not went in my review... Looks like a leftover

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes... i saw that! im remove the devm_action.

@ahaslam2 ahaslam2 force-pushed the axelh/ad5791_offload branch 4 times, most recently from bb84d25 to 64fd6bb Compare November 5, 2024 16:27
@ahaslam2
Copy link
Collaborator Author

ahaslam2 commented Nov 5, 2024

Changes V6:

  • remove devm_add_action_or_reset for pwm
  • use round_up for ad5791_get_sampling_freq
  • actually use pwm-cells <3>
  • add comment for tx_buf workaround for streaming tx.
  • fix space comments


dmas = <&tx_dma 0>;
dma-names = "tx";
pwms = <&adc_trigger 0 1000 0>;
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
pwms = <&adc_trigger 0 1000 0>;
pwms = <&dac_trigger 0 1000 0>;

Looks like a copy-paste from an ADC, but this is a DAC.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok

@ahaslam2 ahaslam2 force-pushed the axelh/ad5791_offload branch from 64fd6bb to 3f44a10 Compare November 7, 2024 13:52
@ahaslam2
Copy link
Collaborator Author

ahaslam2 commented Nov 7, 2024

Changes v7

  • Follow ad7944 example, dont enable/disable pwm on buffer ops. just enable pwm on probe keep it enabled
    this pwm is used for offload only. Bring back the devm_action to disable it automatically.
  • protect spi_read/write raw with "claim direct mode" and drop bus_lock from buffer ops.
  • use dac_trigger instead of adc in dts label.
  • add patch acked upsteam to correct dt example.

return PTR_ERR(st->gpio_clear);

st->gpio_ldac = devm_gpiod_get_optional(&spi->dev, "ldac",
GPIOD_OUT_HIGH);
Copy link
Collaborator

@dlech dlech Nov 7, 2024

Choose a reason for hiding this comment

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

Does this also need to be changed to GPIOD_OUT_LOW since we changed the devcietree to active low?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

might be for legacy reasons but i think the gpio wording is quite confusing
think that "HIGH" actually means "active" ? perhaps why we see several "resets" being
handled in opposite way when i think they are all "active low" ?

for the output to be set according to the DAC register value the actual state of the physical gpio needs to be low
(table 9 p 21 of datasheet) (reset=1 clr=1 ldac=0)

so by setting to out_high the gpio is actually going to low state if is "active low" in dts
at least that is what i measure and see on debugfs:

gpiochip0: GPIOs 2016-2047, parent: platform/ff210080.gpio_bd, /soc/axi_h2f_lw_bridge@0xff200000/gpio_bd@0x00010080:
gpio-2032 ( |reset ) out hi ACTIVE LOW
gpio-2033 ( |clear ) out hi ACTIVE LOW
gpio-2034 ( |ldac ) out lo ACTIVE LOW

Copy link
Collaborator

Choose a reason for hiding this comment

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

think that "HIGH" actually means "active" ?

yes, or "asserted"

@ahaslam2
Copy link
Collaborator Author

ahaslam2 commented Nov 8, 2024

the ci error is due to the fixes tag from the upstream patch:
WARNING: Unknown commit id 'baaa92d284d5', maybe rebased or not pulled?
#10:
Fixes: baaa92d ("dt-bindings: iio: dac: ad5791: Add optional reset, clr and ldac gpios")

Depending on board layout, the ad57xx may need control of reset, clear,
and ldac pins by the host driver. Add optional bindings for these gpios.

Reviewed-by: David Lechner <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Axel Haslam <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jonathan Cameron <[email protected]>
Vcc, iovcc, vrefp, and vrefn are needed for the DAC to work.
Add them as required bindings for ad5791.

Reviewed-by: David Lechner <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Axel Haslam <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jonathan Cameron <[email protected]>
On the example, the ldac gpio is flagged as active high, when in reality
its an active low gpio. Fix the example by using the active low flag for
the ldac gpio.

Signed-off-by: Axel Haslam <[email protected]>
Include a chip info struct in device SPI and device OF match tables to
provide channel definitions for each particular ADC model and drop
device enum.

Suggested-by: Nuno Sa <[email protected]>
Reviewed-by: David Lechner <[email protected]>
Signed-off-by: Axel Haslam <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jonathan Cameron <[email protected]>
The ad7591 has reset, clr and ldac gpios. For the DAC to output data
continuously written to the data register the state of these gpios needs
to be set by the driver.

Add these gpios to the driver making them optional in case they are fixed
on the pcb.

Reviewed-by: David Lechner <[email protected]>
Signed-off-by: Axel Haslam <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jonathan Cameron <[email protected]>
Simplify probe by using of the devm_regulator_get_enable_read_voltage.

Suggested-by: David Lechner <[email protected]>
Reviewed-by: David Lechner <[email protected]>
Signed-off-by: Axel Haslam <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jonathan Cameron <[email protected]>
Use devm_iio_device_register to automatically free the iio device.
since this is the last remaining resource that was not automatically
freed, we can drop the ".remove" callback.

Suggested-by: David Lechner <[email protected]>
Reviewed-by: David Lechner <[email protected]>
Signed-off-by: Axel Haslam <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jonathan Cameron <[email protected]>
This property is not defined on the binidngs, and is not used by the
driver. Remove it

Suggested-by: David Lechner <[email protected]>
Signed-off-by: Axel Haslam <[email protected]>
This adds the bi-directional gpio block to the d10 nano

Signed-off-by: Axel Haslam <[email protected]>
Add devicetree for ad57xx on de10nano.

Signed-off-by: Axel Haslam <[email protected]>
To allow offload to stream a "tx" type of xfer we need the write flag
set but no messages on the SDO memory of the offload engine. but the
current code relies on the tx_buf pointer for both of these operations,
so there is no way to separate the two.

The offload patches currently on development for upstream add flags on
core spi structures to flag an offload xfer as a streaming xfer.

While those patches get review and are ready to backport to the adi
tree, Workaround this limitation by checking if the tx_buf address is
-1 to flag it as "streaming type".

Signed-off-by: Axel Haslam <[email protected]>
Add spi offload support to stream tx buffers using dma.
This allows loading samples to the  dac with a rate of 1 MSPS.

Signed-off-by: Axel Haslam <[email protected]>
@ahaslam2 ahaslam2 force-pushed the axelh/ad5791_offload branch from 3f44a10 to de61469 Compare December 5, 2024 13:37
@ahaslam2
Copy link
Collaborator Author

ahaslam2 commented Dec 5, 2024

Changes re-based/tested on new kernel in main v6.6.

requires #2666

i remove the fixes tag, so CI would be happy.

@dlech dlech mentioned this pull request Dec 9, 2024
6 tasks
@ahaslam2 ahaslam2 merged commit a339b25 into main Dec 12, 2024
13 checks passed
@ahaslam2 ahaslam2 deleted the axelh/ad5791_offload branch December 12, 2024 09:58
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.

4 participants