-
Notifications
You must be signed in to change notification settings - Fork 911
ADF41513 Driver implementation #3012
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: mirror/jic23/iio/testing
Are you sure you want to change the base?
Conversation
ccd64ff to
76e3d30
Compare
drivers/iio/frequency/adf41513.c
Outdated
| struct adf41513_platform_data *pdata; | ||
| struct iio_dev *indio_dev; | ||
| struct adf41513_state *st; | ||
| struct clk *ref_clk; |
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.
| struct clk *ref_clk; | |
| struct clk *ref_clk = NULL; |
if (pdata->clkin), ref_clk is never set.
drivers/iio/frequency/adf41513.c
Outdated
| if (st->ref_clk) | ||
| st->ref_freq_hz = clk_get_rate(st->ref_clk); | ||
| else | ||
| st->ref_freq_hz = pdata->clkin; |
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 (st->ref_clk) | |
| st->ref_freq_hz = clk_get_rate(st->ref_clk); | |
| else | |
| st->ref_freq_hz = pdata->clkin; | |
| if (pdata->clkin) | |
| st->ref_freq_hz = pdata->clkin; | |
| else | |
| st->ref_freq_hz = clk_get_rate(st->ref_clk); |
flows a little more naturally IMO, since ref_clk is set if clkin is not set
61944f0 to
c9591d3
Compare
drivers/iio/frequency/adf41513.c
Outdated
| struct mutex lock; | ||
|
|
||
| /* Cached register values */ | ||
| u32 regs[14]; |
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.
array size is 14, can there array size used as define? Later on the REG0 and REG13 used in for loop. could be from MAX_REG number to 0. Assume no more the 14 registers are used?
c9591d3 to
65e501e
Compare
nunojsa
left a 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.
Just some comments about using legacy platform_data. Once you mark this ready for reviewing I'll give a more in depth review.
| * @load_enable_sync: Enables load enable sync with reference input. | ||
| * @freq_resolution_uhz: Target frequency resolution in uHz (default = 1 Hz). | ||
| */ | ||
| struct adf41513_platform_data { |
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 see this is still a draft but I might just tell it now. Most likely you don't really need the header as I don't expecte anyone other than the driver itself to consume this. So, just move it to the source file.
Another comment is for struct adf41513_platform_data. Name it differently (like adf41513_state or adf41513_data). platform data is a thing from the past :)
drivers/iio/frequency/adf41513.c
Outdated
| return PTR_ERR(pdata); | ||
| } else { | ||
| pdata = spi->dev.platform_data; | ||
| if (!pdata) { |
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 mentioned, drop the platform data stuff. We just want to support FW properties.
76e3d30 to
fe10392
Compare
fe10392 to
f98be31
Compare
nunojsa
left a 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, I'm done for now :). We'll need some iterations on this one and skipped more questionable/complicated things for now. We are also pushing the limits of what can go into a DT property so be ready to justify them when upstreaming.
| maintainers: | ||
| - Rodrigo Alencar <[email protected]> | ||
|
|
||
| description: | |
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.
Likely no need for formatting.
| description: Clock that provides the reference input frequency. | ||
|
|
||
| clock-names: | ||
| const: clkin |
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.
Given that you only have a clock, you might get questioned about the above
| description: Power supply for the device (3.3V) | ||
|
|
||
| chip-enable-gpios: | ||
| description: | |
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.
drop |. Same in all other places
| maximum: 32 | ||
| description: | ||
| Reference division factor (R Counter). If not specified, the driver | ||
| will calculate the optimal value automatically. |
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, we might need to better explain why we would need this as a 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.
those are constraints to the input reference path, I've taken those from adf4350 driver.
drivers/iio/frequency/adf41513.c
Outdated
| /* get lock detect gpio */ | ||
| st->lock_detect = devm_gpiod_get_optional(&spi->dev, "lock-detect", GPIOD_IN); | ||
| if (IS_ERR(st->lock_detect)) { | ||
| dev_err(&spi->dev, "fail to request lock detect GPIO\n"); |
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.
Be consistent. dev_err_probe() in all probe path
drivers/iio/frequency/adf41513.c
Outdated
| } | ||
|
|
||
| /* configure IIO device */ | ||
| indio_dev->name = st->data.name[0] ? st->data.name : "adf41513"; |
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 name should be constant. Just use chip_info struct kind of thing if you need more than the name. Or just a const char pointer passed through of_id and spi_id tables.
drivers/iio/frequency/adf41513.c
Outdated
| return -EINVAL; | ||
| } | ||
|
|
||
| mutex_init(&st->lock); |
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.
devm_mutex_init()
drivers/iio/frequency/adf41513.c
Outdated
|
|
||
| static int adf41513_pm_resume(struct device *dev) | ||
| { | ||
| struct iio_dev *indio_dev = dev_get_drvdata(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.
Pass in your device struct directly in spi_set_drvdata(). Then no need for the pointer dance
950132e to
b60429f
Compare
f98be31 to
3150872
Compare
658fbf4 to
b8cc6c4
Compare
d967ebe to
f0c3212
Compare
nunojsa
left a 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.
Here it goes my second iteration. As I said, this one will take some...
drivers/iio/frequency/adf41513.c
Outdated
| /* REG2 Bit Definitions */ | ||
| #define ADF41513_REG2_PHASE_VAL_MSK GENMASK_U32(15, 4) | ||
| #define ADF41513_REG2_PHASE_VAL(x) FIELD_PREP(ADF41513_REG2_PHASE_VAL_MSK, x) | ||
| #define ADF41513_REG2_PHASE_ADJ_MSK BIT_U32(31) |
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 get it but normally no one really cares about that and use the generic BIT() and GENMASK() macros
drivers/iio/frequency/adf41513.c
Outdated
| #define ADF41513_REG12_LOGIC_LEVEL_MSK BIT_U32(27) | ||
| #define ADF41513_REG12_LOGIC_LEVEL(x) FIELD_PREP(ADF41513_REG12_LOGIC_LEVEL_MSK, x) | ||
| #define ADF41513_REG12_MUXOUT_MSK GENMASK_U32(31, 28) | ||
| #define ADF41513_REG12_MUXOUT(x) FIELD_PREP(ADF41513_REG12_MUXOUT_MSK, x) |
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.
Still not addressed
drivers/iio/frequency/adf41513.c
Outdated
| st->settings.ref_div2 = | ||
| FIELD_GET(ADF41513_REG5_RDIV2_MSK, st->regs_hw[ADF41513_REG5]); | ||
| st->settings.prescaler = | ||
| FIELD_GET(ADF41513_REG5_PRESCALER_MSK, st->regs_hw[ADF41513_REG5]); |
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.
refactor the line break. Just break the line after the first argument of FIELD_PREP() for example
drivers/iio/frequency/adf41513.c
Outdated
| if (!device_property_read_u64(dev, "adi,freq-resolution", | ||
| &st->data.freq_resolution_uhz)) { | ||
| if (!st->data.freq_resolution_uhz) | ||
| return dev_err_probe(dev, -ERANGE, "frequency resolution cannot be zero\n"); |
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.
And upper limit? Do we have one?
drivers/iio/frequency/adf41513.c
Outdated
| } | ||
|
|
||
| st->data.phase_resync_clk_div[1] = 1; | ||
| if (!device_property_read_u32(dev, "adi,12bit-clk2-divider", &tmp)) { |
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 have a slight preference for the following patterh:
ret = device_property_read_u32()
if (ret && ret != -EINVAL)
//some meaningful error other than property not present
return ret;
if (!ret) {
/* validate 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.
documentation says:
* %-EINVAL if given arguments are not valid,
* %-ENODATA if the property does not have a value,
* %-EPROTO if the property is not an array of numbers,
* %-EOVERFLOW if the size of the property is not as expected.
* %-ENXIO if no suitable firmware interface is present.
I dont think the suggested pattern is correct
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.
Well, sometimes you need to look further :). At least for OF:
https://elixir.bootlin.com/linux/v6.17.8/source/drivers/of/property.c#L136
But yes, often I also just go:
ret = device_property_read_u32()
if (!ret) {
// validate it...
}
drivers/iio/frequency/adf41513.c
Outdated
| if (tmp > 7) | ||
| return dev_err_probe(dev, -ERANGE, | ||
| "lock detect count setting too high %u\n", tmp); | ||
| else |
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.
redundant else. Ditto for the other places.
drivers/iio/frequency/adf41513.c
Outdated
|
|
||
| st->data.lock_detect_precision = 0; /* default 0 */ | ||
| if (!device_property_read_u32(dev, "adi,lock-detect-precision", &tmp)) { | ||
| if (tmp > 3) |
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.
Here it's not too obvious what 3 means? Maybe a define for it? Im ok with plain literals when their meaning is straightforward but in this case I not seeing it 😅
drivers/iio/frequency/adf41513.c
Outdated
| /* lock detector settings */ | ||
| st->data.lock_detect_bias = 0; /* default 40 uA */ | ||
| if (!device_property_read_u32(dev, "lock-detect-bias-microamp", &tmp)) { | ||
| tmp = (ADF41513_MAX_LD_BIAS_uA - tmp) / ADF41513_LD_BIAS_STEP_uA; |
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 is questionable? Why do we need it before validating the property? It seems to me you are validating the register value rather than the property.
c416398 to
90a2673
Compare
The driver is based on existing PLL drivers in the IIO subsystem and implements the following key features: - Integer-N and fractional-N (fixed/variable modulus) synthesis modes - High-resolution frequency calculations using microhertz (µHz) precision to handle sub-Hz resolution across multi-GHz frequency ranges - Clock framework integration as a clock provider to expose the output signal for use by other kernel subsystems - IIO debugfs interface for direct register access - Platform data parsing from devicetree including charge pump settings, reference path configuration, lock detect parameters, and muxout options - Power management support with suspend/resume callbacks - Phase resynchronization and load-enable synchronization features - Lock detect GPIO monitoring The driver uses 64-bit microhertz values throughout PLL calculations to maintain precision when working with frequencies that exceed 32-bit Hz representation while requiring fractional Hz resolution. Signed-off-by: Rodrigo Alencar <[email protected]>
ultralow noise PLL frequency synthesizer that can be used to implement local oscillators (LOs) as high as 26.5 GHz Signed-off-by: Rodrigo Alencar <[email protected]>
add documentation for adf41513 driver which describes the device driver files and shows how userspace may consume the ABI for various tasks Signed-off-by: Rodrigo Alencar <[email protected]>
b8cc6c4 to
d5d5fa9
Compare
PR Description
PR Type
PR Checklist