-
Notifications
You must be signed in to change notification settings - Fork 877
ADIS16550 #2510
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?
ADIS16550 #2510
Conversation
ebdf441
to
83a8887
Compare
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.
Some initial review from my side. Some other notes is to refactor some commit messages and titles. You should use iio: imu: ...
for the title. Also, for the the patch introducing the driver we should do better than Integrate ADIS16550 with adis lib
and also on the commit message.
On another topic (and note that I don't care much) I think at this point the code is mostly the original one so you should cherry-pick the patches and keep me as the author (and add your co-developed-by tag). If during review the driver changes in a very significant way then, yes, you should make reverse things (you as author and me with co-dev tag).
Also, addition to MAINTAINERS and ABI docs (for the write lock) are missing
drivers/iio/imu/adis.c
Outdated
@@ -491,6 +494,11 @@ int adis_single_conversion(struct iio_dev *indio_dev, | |||
} | |||
EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB); | |||
|
|||
static struct adis_ops default_ops = { |
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.
static const
... See below.
Also let's call it adis_default_ops or adis_ops or something like that. Key is it should have the adis prefix.
drivers/iio/imu/adis.c
Outdated
|
||
if (!adis->ops->write) | ||
adis->ops->write = __adis_write_reg; | ||
} |
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 simplify this to:
if (!adis->ops)
adis->ops = &default_ops;
I think it's fairly unlikely for us to need a custom read() but not a custom write() and vice-versa. Also that could be made to work by exporting the default functions. This way we can make default_ops
const as well as struct adis_ops *ops;
in struct adis
which is way better.
reg_size = adis->data->diag_stat_size; | ||
|
||
ret = adis->ops->read(adis, adis->data->diag_stat_reg, &status, | ||
reg_size); |
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 call should likely be in patch 1?
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 patch 1 there is already an update of __adis_read_reg_16
using the ops structure (adis->ops->write(adis, reg, val, 2);
). This call was added like this ret = adis->ops->read(adis, adis->data->diag_stat_reg, &status, reg_size);
only because the reg_size is variable now.
Configures the device SYNC pin. The following modes are supported | ||
0 - direct_sync | ||
1 - scaled_sync | ||
$ref: /schemas/types.yaml#/definitions/uint32 |
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.
Since this is new, use strings in here. I think it's the preferred way these days.
drivers/iio/imu/adis16550.c
Outdated
#define ADIS16550_SPI_CRC(x) FIELD_PREP(ADIS16550_SPI_CRC_MASK, x) | ||
#define ADIS16550_SPI_CRC_GET(x) FIELD_GET(ADIS16550_SPI_CRC_MASK, x) | ||
#define ADIS16550_SPI_SV_MASK GENMASK(7, 6) | ||
#define ADIS16550_SPI_SV_GET(x) FIELD_GET(ADIS16550_SPI_SV_MASK, 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.
These days I think Jonathan prefers to have the FIELD_PREP/GET() stuff inline in the code
drivers/iio/imu/adis16550.c
Outdated
goto done; | ||
} | ||
|
||
for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { |
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.
indentations...
kfree(adis->xfer); | ||
adis->xfer = NULL; | ||
return -ENOMEM; | ||
} |
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 most of the above code is duplicated but at this point I'm also not sure that something like an option as .prepare_scan_mode()
or something like that is worth it (at this point).
|
||
tx = adis->buffer + burst_length; | ||
tx[0] = 0x00; | ||
tx[1] = 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 guess we can omit the above two lines (should be 0 already)
drivers/iio/imu/adis16550.c
Outdated
|
||
if (sync_mode >= st->info->num_sync) { | ||
dev_err(dev, "Invalid sync mode: %u for %s\n", sync_mode, | ||
st->info->name); |
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.
dev_err_probe()
. Ditto for the other places
drivers/iio/imu/adis16550.c
Outdated
|
||
ret = devm_add_action_or_reset(dev, adis16550_disable_clk, clk); | ||
if (ret) | ||
return 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.
devm_clk_get_enabled()
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.
changes in v2:
- refactor commit titles.
- add maintainers
- drop
write_lock
custom attr. - use static const for default_ops and add
adis_
prefix - use strings for
sync-mode
- use
FIELD_GET
/FIELD_PREP
inline - drop some
const
- use
GENMASK
where possible - implement set_freq/get_freq based on scale mode.
- fix indentations
- use
dev_error_probe
where possible - use
devm_clk_get_enabled
- add
vdd
regulator
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. Also you need to add your's and Ramona Co-developed-by tag otherwise you'll be asked about all thos sign offs
@@ -520,6 +528,9 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, | |||
|
|||
adis->spi = spi; | |||
adis->data = data; | |||
if (!adis->ops) | |||
adis->ops = &adis_default_ops; |
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.
since we are assuming we always have write() and read() we should sanity check it here (for ops given by drivers).
include/linux/iio/imu/adis.h
Outdated
@@ -115,6 +130,7 @@ struct adis { | |||
|
|||
const struct adis_data *data; | |||
unsigned int burst_extra_len; | |||
const struct adis_ops *ops; |
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.
nit: not aligned with other members
@@ -1293,6 +1293,16 @@ S: Supported | |||
F: drivers/iio/imu/adis16475.c | |||
F: Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml | |||
|
|||
ANALOG DEVICES INC ADIS16550 DRIVER | |||
M: Nuno Sa <nuno.sa@analog.com> |
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.
Since I'm here, I should likely be also in the bindings patch
L: linux-iio@vger.kernel.org | ||
S: Supported | ||
W: https://ez.analog.com/linux-software-drivers | ||
F: Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml |
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 file is introduced in the bindings patch. Hence, the entry should be introduced in that patch...
{ .compatible = "adi,adis16550", .data = &adis16550_chip_info }, | ||
{ } | ||
}; | ||
MODULE_DEVICE_TABLE(of, adis16550_of_match); |
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 spi id table for module auto load
drivers/iio/imu/adis16550.c
Outdated
static void adis16550_debugfs_init(struct iio_dev *indio_dev) | ||
{ | ||
} | ||
#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.
I think this can be done in a better way. Drop the #ifdef CONFIG_DEBUG_FS. Instead add this in the beginning of adis16550_debugfs_init():
if (IS_ENABLED(CONFIG_DEBUG_FS))
return;
And let the compiler remove all the unused API's :)
drivers/iio/imu/adis16550.c
Outdated
__be32 __din[2], __dout[2]; | ||
u16 data = 0; | ||
int ret; | ||
const bool wr = readval ? false : 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.
no need for const...
drivers/iio/imu/adis16550.c
Outdated
|
||
ret = spi_sync(spi, &msg); | ||
if (ret) | ||
return dev_err_probe(&spi->dev, ret, "Spi failure %d\n", 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.
drop dev_err_probe()
. Not always called under probe()
drivers/iio/imu/adis16550.c
Outdated
else if ((writeval >> 16) != data && reg != ADIS16550_REG_COMMAND) | ||
return dev_err_probe(&spi->dev, -EIO, | ||
"Data not written: wr: 0x%04X, rcv: 0x%04X\n", | ||
writeval >> 16, 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.
ditto
drivers/iio/imu/adis16550.c
Outdated
if (crc_rcv != crc) | ||
return dev_err_probe(&adis->spi->dev, -EIO, | ||
"Invalid crc, rcv: 0x%02x, calc: 0x%02x!\n", | ||
crc_rcv, crc); |
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 `dev_err_probe(). Normal dev_err()
This patch introduces a custom ops struct letting users define custom read and write functions. Some adis devices might define a completely different spi protocol from the one used in the default implementation. Co-developed-by: Ramona Gradinariu <ramona.gradinariu@analog.com> Signed-off-by: Ramona Gradinariu <ramona.gradinariu@analog.com> Co-developed-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Some devices may have more than 16 bits of status. This patch allows the user to specify the size of the DIAG_STAT register. It defaults to 2 if not specified. This is mainly for backward compatibility. Co-developed-by: Ramona Gradinariu <ramona.gradinariu@analog.com> Signed-off-by: Ramona Gradinariu <ramona.gradinariu@analog.com> Co-developed-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
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.
v3:
- add proper co-developed-by tags
- align members in struct adis.
- add MAINTAINERS per patch
- add spi id table
- use static const
- use device_get_match_data
- use device_property_match_string
- return error if property not found for scaled frequency
- drop const where redundant
- drop extra line.
- use IS_ENABLED(CONFIG_DEBUG_FS)
- drop
dev_err_probe
where iti doesn't apply.
Document the ADIS16550 device devicetree bindings. Co-developed-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Ramona Gradinariu <ramona.gradinariu@analog.com>
The ADIS16550 is a complete inertial system that includes a triaxis gyroscope and a triaxis accelerometer. Each inertial sensor in the ADIS16550 combines industry leading MEMS only technology with signal conditioning that optimizes dynamic performance. The factory calibration characterizes each sensor for sensitivity, bias, and alignment. As a result, each sensor has its own dynamic com- pensation formulas that provide accurate sensor measurements Co-developed-by: Ramona Gradinariu <ramona.gradinariu@analog.com> Signed-off-by: Ramona Gradinariu <ramona.gradinariu@analog.com> Co-developed-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Add documentation for adis16550 driver which describes the driver device files and shows how the user may use the ABI for various scenarios (configuration, measurement, etc.). Co-developed-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Signed-off-by: Ramona Gradinariu <ramona.gradinariu@analog.com>
Add entry for the ADIS16550 driver. Signed-off-by: Ramona Gradinariu <ramona.gradinariu@analog.com>
d90670a
to
cedd2c0
Compare
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.
Some stuff that yo're still not addressing. Anyways, I think we can speed things up and send it upstream and continue from there.
.name = "adis16550", | ||
.of_match_table = adis16550_of_match, | ||
}, | ||
.probe = adis16550_probe, |
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.
spi_device_id not being used...
else if (!strcmp(str, "scaled_sync")) | ||
sync_mode = 1; | ||
else | ||
return -EINVAL; |
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.
Oh my bad... the above does not look neat.
Check this one:
fwnode_property_match_property_string()
Though I would look in linux-next to see of there's any device_property_match_property_string() variant
* In pps scaled sync we must scale the input clock to a range | ||
* of [3000 45000]. | ||
*/ | ||
ret = device_property_read_u32(dev, "adi,scaled-output-hz", |
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 seems to me this is still doing things in a very old fashioned way... Look at this one:
https://elixir.bootlin.com/linux/v6.11-rc7/source/drivers/iio/imu/adis16475.c#L1824
Likely it's the same deal here?
{ | ||
struct adis *adis = iio_device_get_drvdata(indio_dev); | ||
u8 *tx; | ||
const u16 burst_length = ADIS16550_BURST_DATA_LEN; |
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 const
break; | ||
} | ||
} | ||
|
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.
Did you tried the above and for some reason it did not worked?
return 0; | ||
} | ||
|
||
static int adis16550_set_gyro_filter_freq(struct adis16550 *st, int freq) |
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.
unsigned int...
|
||
return __adis_update_bits(&st->adis, ADIS16550_REG_CONFIG, | ||
ADIS16550_GYRO_FIR_EN_MASK, | ||
(u32)FIELD_PREP(ADIS16550_GYRO_FIR_EN_MASK, en)); |
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.
Why the unlocked version? My other comment still holds valid for the possible values of freq
if (freq) | ||
en = true; | ||
|
||
return __adis_update_bits(&st->adis, ADIS16550_REG_CONFIG, |
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.
needs to be locked
return ret; | ||
} | ||
|
||
static int adis16550_get_accl_filter_freq(struct adis16550 *st, int *freq) |
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 below 4 functions look really similar. There#s high odds they can be combined in just 2 functions
static void adis16550_debugfs_init(struct iio_dev *indio_dev) | ||
{ | ||
if (!IS_ENABLED(CONFIG_DEBUG_FS)) | ||
return; |
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.
Odd place for this... Put it below declarations
PR Description
necessary to understand them. List any dependencies required for this change.
any space), or simply check them after publishing the PR.
description and try to push all related PRs simultaneously.
PR Type
PR Checklist