-
Notifications
You must be signed in to change notification settings - Fork 844
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
Wip/bl/ad3552r v1 #2525
base: Wip/bl/ad3552r/base
Are you sure you want to change the base?
Wip/bl/ad3552r v1 #2525
Conversation
192d7eb
to
d249dcc
Compare
Hi Nuno,
Will be back on monday 22. |
Hi @nunojsa, i am back on this, any comment on this job ? |
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.
Just did a very small review since I think main thing for now is to figure how the new interfaces should look like.
drivers/iio/dac/adi-axi-dac.c
Outdated
.set_sample_rate = axi_dac_set_sample_rate, | ||
.qspi_set_stream_state = axi_dac_qspi_set_stream_state, | ||
.qspi_get_stream_state = axi_dac_qspi_get_stream_state, | ||
.qspi_update_chan_reg_addr = axi_dac_qspi_update_chan_reg_addr, |
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.
Not commenting much the above three interfaces for now. But why do we need them? What's the purpose? I'm asking because I want to have (or at least try) something way more generic than the above which is "attached/dedicated" to a qspi bus
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.
@nunojsa I mainly added interfaces for all the operations that uses the axi regmap.
stream_state actually starts and stop the stream (dma transfer). Starting the stream i see the generated output by oscilloscope.
I see that i should be able to remove them. obtaining the same from the frontend, using more generic iio_backend_bus_send() and iio_backend_bus_recv()
drivers/iio/dac/adi-axi-dac.c
Outdated
.qspi_update_chan_reg_addr = axi_dac_qspi_update_chan_reg_addr, | ||
.qspi_read_reg = axi_dac_qspi_read_reg, | ||
.qspi_write_reg = axi_dac_qspi_write_reg, | ||
.qspi_update_reg_bits = axi_dac_qspi_update_reg_bits, |
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.
Again, the above is just too directed to a qspi bus. I would prefer something more generic. Like:
iio_backend_bus_send(backend, const char *buf, size_t len);
iio_backend_bus_recv(backend, char *buf, size_t len);
Then, backend drivers do what they have to depending on the bus interface. I guess we may have more in the future. Hence, trying to come up with some kind of protocol may not be feasible and with the above, things are transparent for the framework as it's up to the frontend and backend to make it right. I'm also using a plain buffer instead of using a register and value variable pair as I can foresee things like CRC being needed.
Also note that .qspi_update_reg_bits is not really needed. You can very well implement that at the framework level with read()/write(). No need for a new op.
Last thing that comes to mind is that this likely needs a devicetree property indicating the backend as bus capabilities (like is being used to write/read device registers). Reason is that we don't want to expose these interfaces in all designs (just the ones that really have such an interface)
Please talk with @dlech... I discussed something like the above with him IIRC
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 thinking on this particular chip is that we could:
- Convert the existing upstream driver to use SPI regmap.
- Add a backend function like
iio_backend_get_frontend_regmap()
.- This would return a regmap that is implemented with the proposed
axi_dac_qspi_read_reg
andaxi_dac_qspi_write_reg
functions (replacingqspi
withfrontend
to make the names more generic). - This would allow much of the code in the existing upstream ad3552r driver to be reused as-is because of the regmap abstraction.
- This would return a regmap that is implemented with the proposed
- Split the existing driver into a SPI module with a SPI device probe function and an IIO backend module with a platform device probe function. (Or is it possible to have two
module_driver()
in one module?)- The majority of the existing driver would be in a common file shared by both the SPI module and platform device module.
- The only difference between the two drivers would be a little bit in the probe function and how buffered writes are implemented.
Alternately, we could add the iio_backend_bus_send()
and iio_backend_bus_recv()
functions to the backend instead of `iio_backend_get_frontend_regmap() and implement the regmap that calls those in the ad3552r platform driver and still get the same code sharing benefit.
What do you think of this approach @nunojsa?
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.
Add a backend function like iio_backend_get_frontend_regmap()
Hmm creating a bi-directional link between backends and frontends may be a very good way to shoot ourselves in the foot :). Right now the expectation is that frontends cannot exist if backends are not available (which is guaranteed with device_links). If we now create an API from a backend to access a frontend, we would then need to make sure the frontend is available while we need whatever resource we get from it. So we create kind of deadlock dependency. Might be doable but will add a lot of complexity that I would prefer to avoid.
Split the existing driver into a SPI module with a SPI device probe function and an IIO backend module with a platform device probe function. (Or is it possible to have two module_driver() in one module?)
I think you can't... I did had some issues with it. It may be related to be two driver's of the same time but I don't think so. I guess it's more related with module_init() macro when CONFIG_MODULE is enabled. But you can anyways have your own explicit module_init()/module_exit() calls and register multiple drivers from your init function - not seeing a reason for that not to work.
Alternately, we could add the iio_backend_bus_send() and iio_backend_bus_recv() functions to the backend instead of `iio_backend_get_frontend_regmap() and implement the regmap that calls those in the ad3552r platform driver and still get the same code sharing benefit.
I may be biased but I think the above is my preference for now. Hope my arguments for it make sense to you @dlech
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.
creating a bi-directional link between backends and frontends may be a very good
Maybe "frontend" is not the right word choice. I am not suggesting that the backend driver communicate with the frontend driver, only the frontend chip.
Right now the expectation is that frontends cannot exist if backends are not available
This is exactly what I am suggesting. The frontend driver can't work unless it gets the physical bus access functions from the backend.
Anyway, the main point is that we should be able to share quite a bit of code, e.g. all of the regulator stuff and any other hardware that doesn't go through the backend. And if we use the regmap abstraction, then we could share chip configuration functions for both the SPI bus and the AXI ADC backend versions of the driver.
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.
thanks for the comments / help.
Current PR keeps generic-spi (spi driver, ad3552r.c) and adds ad3552r-axi.c version (platform driver). SPI registers and bitmasks are now shared in a common header.
Common code is actually
- reading product id
- setting voltage ranges
- voltage reference config
The axi version is actually a small driver, implemented for maximum speed, it has minimal/fixed configuration (some settings are applied the same for both channels), and uses some special commands not existing in the generic-spi.
It's ok for me the approach by implementing
iio_backend_bus_send(backend, const char *buf, size_t len);
iio_backend_bus_recv(backend, char *buf, size_t len);
What about in ad3552r_common.c to just pass a regmap * to the spi read / write common functions ?
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.
Anyway, the main point is that we should be able to share quite a bit of code, e.g. all of the regulator stuff and any other hardware that doesn't go through the backend. And if we use the regmap abstraction, then we could share chip configuration functions for both the SPI bus and the AXI ADC backend versions of the driver.
Indeed, your naming got me confused but I guess I now understand what you mean. Basically, you're saying for the bakend to implement a custom regmap_bus and then the frontend driver would get a pointer to that regmap_bus right? Hmm, this is an interesting idea yes... I don't think this is as flexible as the send()/recv() approach but should do the trick 99% of the time and it is more practical (and we can make use of apis like update_bits()).
Alright, I like the two approaches so I'm leaving that up to you guys to decide....
What about in ad3552r_common.c to just pass a regmap * to the spi read / write common functions ?
Not sure I'm following this? But anyways, if we go the regmap direction I guess you can just regmap APIs for both the axi and the spi version. If we use the recv()/send() approach you can just pass in an ops struct with write() and read() callback and implement them from the axi and spi drivers.
d249dcc
to
5eba63b
Compare
Please let me know if i am going in the correct direction. Add a new version (a first intermediate step for what has been discussed):
|
drivers/iio/industrialio-backend.c
Outdated
* RETURNS: | ||
* 0 on success, negative error number on failure. | ||
*/ | ||
int iio_backend_update_chan_reg_addr(struct iio_backend *back, u32 chan_address) |
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 don't really understand what this function does. But I see that it is called in ad3552r_axi_update_scan_mode()
. So it makes me think we might be able to use the existing iio_backend_chan_enable()
and iio_backend_chan_disable()
functions instead.
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.
We could use that. Maybe is more setting "what" channel, but i can go with enable/disable.
AD3552R_REG_ADDR_CH_DAC_16B(0);
AD3552R_REG_ADDR_CH_DAC_16B(1);
AD3552R_REG_ADDR_CH_INPUT_24B(0);
AD3552R_REG_ADDR_CH_INPUT_24B(1);
looks like iio_backend_data_format_set may suit better, since just the channel register offset is updated 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.
@dlech No as of now, i cannot find any available call to be used. The value that get written is the address of the register where the samples will be written. Can be the 16 or 24 bit sample register, and the value is driver (chip) specific.
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.
OK. I understand now.
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.
Can we somehow map the channel address with the channel number? I definitely think the naming is too specific for this usecase but I'm still not sure what would be a better on. Maybe iio_backend_data_transfer_from() or iio_backend_update_sample_from()? And rename chan_address -> address. At this point not sure it's that meaningful to have chan_
But more importantly this clearly needs a description. Use the usecase you're familiar with but try to keep it generic.
Like "Some devices may need to inform the backend an adress/localtion where to load data from"
Not sure if the above really makes sense for this device but I guess you got the idea.
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.
Thanks. I changed it to iio_backend_data_transfer_addr() for now, as more generic as possible, adding a meaningful description, as "Some devices may need to inform the backend about an adress/location where to read or write the data."
I will keep looking at this next week. The documentation at http://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html is not very good for understanding what some of the AXI DAC registers do, so more comments in the code could help us understand better why certain operations are needed and what they actually do. |
@dlech Still not fully clear to me. Btw, adding some comments where possible. |
5eba63b
to
84b0393
Compare
@dlech
|
If the HDL project for AD3552R has extra memory mapped registers that are not present in the generic AXI DAC IP block, then it could make sense to add an extra compatible string to But, if all of the registers are the same as the generic AXI DAC IP core, then we should not need this extra compatible string. I didn't look at ever single register, but the register map from http://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html looks the same as the generic one from https://wiki.analog.com/resources/fpga/docs/axi_dac_ip, so maybe the are the same? |
drivers/iio/dac/ad3552r-axi.c
Outdated
if (ret) | ||
return ret; | ||
|
||
st->ref_clk = devm_clk_get_prepared(&pdev->dev, NULL); |
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 think we should use iio_backend_set_sampling_freq()
in ad3552r_axi_write_raw()
instead of getting the clock here since the clocks isn't connected to the DAC chip.
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.
@dlech not clear. QSPI has a clock, connected from xilinx (fpga) pad to the DAC chip. But should be handled fully from fpga HDL. I removed fdt clock reference and as well the clk enable, all works properly.
iio_backend_set_sampling_freq() seems not impacting on this clock.
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.
So, this is my understanding.
- DAC sample rate in direct write is dependent from the QSPI clock.
- AXI DAC starts using a (probably fixed) QSPI clock of 66MHZ. In DDR we have 132/4 (to have 16bit samples) so we have 33 MUPS (as declared from the datasheet "Dual Channel, 16-Bit, 33 MUPS"
- So sample rate is connected to the interface clock, and RATECNTRL may be able to change it, but there is no api in the backend still for this. Not sure if it's the case to add it.
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 tried to write RATECTRL register, the only writable, clock seems always fixed at 66Mhz, whatever value i write on it.
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 think the RATECTRL is only meaningful for the IP internal DDS... In theory, you can get the interface frequency with CLK_FREQ and CLK_RATIO and then use the RATECTRL to decimate the internal sampling frequency. However, on the design I tried this (which is an old one) changing the RATECTRL seemed to have no effect.
In current implementation, iio_backend_set_sampling_freq() is only meaningful you DDS is supported and you're exposing the core ALTVOLTAGE channel.
The reason why I use iio_backend_set_sampling_freq() which honestly is not something I really like is:
- The value you get in the CLK_FREQ register is measured by the IP so you do have some rounding that could potential be an issue in some cases (not sure though).
- More importantly, the way to actually get the sampling frequency is not the same for all designs. So I would prefer to have some more info in the IP in order to be able to do it in a generic way.
For the above reasons I went with iio_backend_set_sampling_freq() which is nothing more than notifying the backend of the interface clock (which is the same as the sampling frequency for RATECNTRL = 1) since often the interface clock comes from the converter. Hopefully this can be improved at some point.
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.
Looks good, if I'm not missing nothing that should mean that you're measuring approx 133332824. If DDR is on that matches the 66MHz.
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.
Not clear from where you get 133332824, could you explain ?
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.
The docs say:
This is relative to the processor clock and in many cases is 100MHz. The number is represented as unsigned 16.16 format.
So the calculation would be something like:
unsigned long system_clk_hz = 100 * MEGA; /* TODO: get this using clk_get_rate() */
u32 clk_freq = 87381; /* TODO: actually read from CLK_FREQ register */
u32 clk_ratio = 1; /* TODO: actually read from CLK_RATIO register */
/* convert from 16.16 format to hz relative to system_clk_hz */
u16 int_val = reg_val >> 16;
u16 frac_val = reg_val & 0xFFFF;
u32 interface_clk_hz = (int_val * system_clk_hz + mul_u64_u32_div(frac_val, system_clk_hz, UINT16_MAX)) * clk_ratio;
Here, interface_clk_hz
should be approx 133_333_333 (~133MHz).
Then the docs say:
Note that the actual sampling clock may not be the same as the interface clock- software must consider device specific implementation parameters to calculate the final sampling clock.
So this would probably be the 133MHz interface clock times 2 for DDR transferring 2 bits per clock cycle, times 4 for QSPI transferring 4 bits at a time, divided by 16 bits per sample to get the 66MHz sample rate. (Datasheet max sample rate is 33MHz, but I assume that is dividing 66MHz by 2 channels)
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.
Not clear from where you get 133332824, could you explain ?
Pretty much what @dlech has above... But note that I already explained why I did not went with this before. Normally, getting the internal core sample rate is only meaningful if the internal DDS is being used.
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.
Thanks.
@nunojsa Resgister offsets and names are the same. Issue is the "CUSTOM" register, that can be used in different ways depending on the IP. What about a write_custom_reg() api ? |
2d045d7
to
e94157b
Compare
c8895be
to
880e5c6
Compare
880e5c6
to
38ac22a
Compare
1efec0b
to
38ac22a
Compare
drivers/iio/dac/ad3552r-axi.c
Outdated
return err; | ||
} | ||
|
||
err = iio_backend_ddr_enable(st->back); |
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 we need to call iio_backend_ddr_disable()
if any of the later functions returns an error?
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.
done
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 don't see where this is done before this function returns.
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.
Another round from me. Main pain point for now (unless I'm missing something) is to properly get the sampling frequency.
Also, the bus stuff is getting better but I might still push for the regmap based API 😉 . I feel it brings added value so at least a try could be worth it (to take an actual look on how it would look like)
drivers/iio/dac/adi-axi-dac.c
Outdated
err = axi_dac_bus_reg_write(back, | ||
AXI_DAC_RD_ADDR(reg), 0, val_size); | ||
if (err) | ||
return err; |
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 weird enough that maybe it deserves a comment on why we have to write the register with a value of 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.
This comes from the original driver, can try to investigate. Looks like a write of 0 and a check for busy is needed for a next correct write.
drivers/iio/dac/adi-axi-dac.c
Outdated
bval, bval != AXI_DAC_BUSY, | ||
10, 100); | ||
if (err) | ||
return err; |
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.
The above poll should be guaranteed by axi_dac_bus_reg_write()
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.
sorry, not clear
drivers/iio/dac/ad3552r-axi.c
Outdated
|
||
switch (mask) { | ||
case IIO_CHAN_INFO_SAMP_FREQ: | ||
return iio_backend_read_raw(st->back, chan, val, val2, 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.
As I commented before, what value are you getting in here? My expectation (assuming the backend gives us SCLK) for this would be something like:
ret = iio_backend_read_raw(st->back, chan, val, val2, mask);
if (ret)
return ret;
*val = DIV_ROUND_CLOSEST(*val * (1 + ddr_en)) * n_spi_lanes, sample_size)
All of the above info should be something that we could easily know in the frontend driver. It#s just that what we get from the backend is not what I would expect (I think). But see my other comment
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.
Let's see the code i pushed.
38ac22a
to
9952fc3
Compare
@@ -59,3 +59,11 @@ Description: | |||
multiple predefined symbols. Each symbol corresponds to a different | |||
output, denoted as out_voltageY_rawN, where N is the integer value | |||
of the symbol. Writing an integer value N will select out_voltageY_rawN. | |||
|
|||
What: /sys/bus/iio/devices/iio:deviceX/out_voltage_synchronous_mode | |||
KernelVersion: 6.11 |
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.
KernelVersion: 6.11 | |
KernelVersion: 6.13 |
Jonathan stops taking new code at rc6 and we'll want Nuno's approval on this series when he gets back, so 6.13 will likely be the version this actually lands in.
@@ -38,6 +38,13 @@ properties: | |||
clocks: | |||
maxItems: 1 | |||
|
|||
bus-type: |
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.
Jonathan always suggests to add a default value for when the property is not present. So we should add that. Otherwise, I think maintainers will say the same as Nuno that this should be a boolean property since it only has one value. I guess parallel
makes sense as the default since that is what the existing user of the AXI DAC has?
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.
In the code there is no handling for the parallel bus, so not totally sure adding "parallel" here now is appropriate.
Also adding parallel here means roll back again to a switch/case, considering also parallel.
What about, as i initially did, to add AXI_DAC_BUS_TYPE_NONE as 0 ? And setting default 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.
From the point of view of the device tree that is describing the wiring, there is always going to be some kind of bus that is connected to the DAC chip, so I don't think "none" makes sense to put in the device tree. I suggested "parallel" as the default since the one already existing user of the AXI DAC (ad9739a) uses a parallel bus connection.
#include <linux/iio/buffer.h> | ||
#include <linux/iio/backend.h> | ||
#include <linux/iopoll.h> | ||
#include <linux/of.h> |
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.
#include <linux/of.h> | |
#include <linux/mod_devicetable.h> |
It doesn't look like we actually need the of
header.
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 already checked includes one by one, all are needed. of.h actually is needed for the fwnode_handle, Tried mod_devicetable.h, it is not helping.
I tried #include <linux/fwnode.h>
Still getting errors related to __free and cleanup of fwnode_handle
Seems i need to keep linux/of.h
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.
__free
comes from linux/cleanup.h
.
drivers/iio/dac/ad3552r-axi.c
Outdated
#include <linux/gpio/consumer.h> | ||
#include <linux/iio/buffer.h> | ||
#include <linux/iio/backend.h> | ||
#include <linux/iopoll.h> |
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.
#include <linux/iopoll.h> |
Doesn't look like we are using anything from this header.
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.
as above, all includes are used, removing it i get errors on msleep, fsleep, so i can replace it with delay.h. Done
drivers/iio/dac/adi-axi-dac.c
Outdated
if (data->type == IIO_BACKEND_DATA_UNSIGNED) | ||
/* | ||
* AXI_DAC_REG_CNTRL_2 BIT(4) selects the data format, | ||
* (on web doc page meaning is inverted): |
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.
Can we fix the docs instead of making this comment?
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.
Ok let's see what the HDL guys say
It is possible the HDL has a bug, anbd not the docs ?
9952fc3
to
2e8bd11
Compare
|
Add new ad3552r-axi devicetree. Signed-off-by: Angelo Dureghello <[email protected]>
Add nodes and example related to the DAC AXI IP version of the ad3552r driver. Considering the target DAC chip is the same, even if the controller interface is different, using the same fdt node. Signed-off-by: Angelo Dureghello <[email protected]>
b5c65d1
to
6959b69
Compare
If it is always required, can we remove the sysfs attribute and just always enable it for now? |
drivers/iio/dac/ad3552r-axi.c
Outdated
return 0; | ||
} | ||
|
||
static int ad3552r_axi_update_scan_mode(struct iio_dev *indio_dev, |
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 function still lacks error unwinding and things will be in a bad state if there is ever an error.
Also, some of this should be moved to the postenable
callback so that it is balanced with the predisable
callback. I.e. since we disable DDR mode in predisable
, we should be enabling DDR mode in postenable
so that everything is balanced.
It should also be fine to move everything from here to postenable
and remove the scan_mode
callback if needed.
The way the core code works, if postenable
fails, there is nothing to unwind what was done in update_scan_mode
, so update_scan_mode
should not be changing any settings like DDR mode that are required to be undone later for proper operation of the chip.
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.
About EXT_SYNC, it is used in another project, i don't think we should enable it always, since we don't have any external trigger.
DDR is actually enabled in the same place and sequence where it was in the original driver. It was functional that way and didn't touched the sequence. Ok, i can put all quite in post_enable, except the channel mask, so we still need update_scan_mode.
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 enabling EXT_SYNC depends on which HDL project is being used, then this seems like something that should be coming from the compile feature register in AXI DAC or from the devicetree (e.g. different compatible string for each HDL project). It doesn't seems like this is something that usespace should be expected to enable or disable depending on which HDL project is being used.
drivers/iio/dac/ad3552r-axi.c
Outdated
case IIO_CHAN_INFO_SAMP_FREQ: { | ||
int clk_rate; | ||
|
||
err = iio_backend_read_raw(st->back, chan, &clk_rate, 0, 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.
This one still seems odd to me because we are requesting the sample frequency from the backend, but the value that is returned is not the sample rate, but rather the interface clock rate. It would make more sense if the backend could just return the sample rate directly.
#define AD3552R_CHANNEL(ch) { \ | ||
.type = IIO_VOLTAGE, \ | ||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
.info_mask_shared_by_all = (((ch) == 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.
.info_mask_shared_by_all = (((ch) == 0) ? \ | |
.info_mask_shared_by_all = (((ch) == 0) ? \ |
The (ch) == 0
check is not needed since this is info_mask_shared_by_all
. It doesn't hurt to have it declared more than once. The IIO core code will filter out the duplicates.
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.
Backend cannot know ad5332r DAC IP specs (divide /4 or /8). Changed to IIO_CHAN_INFO_FREQUENCY, could be better..
return -EINVAL; | ||
|
||
err = ad3552r_get_output_range(st->dev, st->chip_id, child, &range); | ||
if (err) |
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.
Looks like this still needs to be fixed.
return 0; | ||
} | ||
|
||
static int ad3552r_axi_setup(struct ad3552r_axi_state *st) |
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 function is missing some of the functionality from ad3552r_configure_device()
in the existing upstream driver.
This is needed to enable regulators and configure a register based on the voltage level.
And we need to handle the "adi,sdo-drive-strength" DT property.
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.
Hi @dlech
fixed all the above,
- add custom range setup
- add regulator setup
- add drive strength setup
- move as much setup code as possible as common code
0e25471
to
0c4cafa
Compare
drivers/iio/dac/ad3552r.h
Outdated
AD3552R_CH_OUTPUT_RANGE_NEG_10__10V, | ||
}; | ||
|
||
u16 ad3552r_field_prep(u16 val, u16 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.
Are we going to replace this with FIELD_PREP
?
This could be in a separate patch at the beginning of the series and Jonathan might apply it right away since that change is a good cleanup to have anyway.
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 tired but i get errors in some case. As
warning: comparison of constant ‘18446744073709551615’ with boolean expression is always false [-Wbool-compare]
BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) >
^
././include/linux/compiler_types.h:490:9: note: in definition of macro ‘__compiletime_assert’
Extend backend features with new calls needed later on this patchset from axi version of ad3552r. A bus type property has been added to the devicetree to inform the backend about the type of bus (interface) in use bu the IP. The follwoing calls are added: iio_backend_ext_sync enable synchronize channels on external trigger iio_backend_ddr_enable enable ddr bus transfer iio_backend_set_bus_mode select the type of bus, so that specific read / write operations are performed accordingly iio_backend_buffer_enable enable or disable buffer iio_backend_data_transfer_addr define the target register address where the DAC sample will be written. iio_backend_bus_reg_read generic bus write, bus-type dependent iio_backend_bus_read generic bus read, bus-type dependent Signed-off-by: Angelo Dureghello <[email protected]>
Extend DAC backend with new features required for the AXI driver version for the a3552r DAC. Signed-off-by: Angelo Dureghello <[email protected]>
Add bus property. Signed-off-by: Angelo Dureghello <[email protected]>
Changes to use FIELD_PREP, so that driver-specific ad3552r_field_prep is removed. Variables (arrays) that was used to call ad3552r_field_prep are removerd too. Signed-off-by: Angelo Dureghello <[email protected]>
Extracting common code, to share common code to be used later by the AXI driver version (ad3552r-axi.c). Signed-off-by: Angelo Dureghello <[email protected]>
Add support for ad3552r AXI DAC IP version. Signed-off-by: Angelo Dureghello <[email protected]>
Some DACs as ad3552r need a synchronous mode setting, adding this parameter for ad3552r and for future use on other DACs, if needed. Signed-off-by: Angelo Dureghello <[email protected]>
0c4cafa
to
1b1a492
Compare
Hi Nuno and all,
so, to take advantage from your review of yesterday, i added some qspi apies. You can have a look.
In the backend there is still "get_regmap" now active, until i find how to implement:
Important, in adi-linux "main" all the recent dac backend stuff is missing, so i ported needed parts just for test now. The
last 5 commits should be reviewed, same code runs on mainline linux now.
Note:
i cannot have ad3552r (cn0585_v1 branch) pyadi-iio python test working since in recent kernel "watermark" sysfs attribute is set readonly. Also some specific IOCTL are missing, so getting warning i cannot reach high speed and test fails. I tested anyway that i can write on buffer in dma_input, so the driver should work as expected.