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

ADIS16550 #2510

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

ADIS16550 #2510

wants to merge 6 commits into from

Conversation

rbolboac
Copy link
Contributor

@rbolboac rbolboac commented Jun 13, 2024

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)

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.

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

@@ -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 = {
Copy link
Collaborator

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.


if (!adis->ops->write)
adis->ops->write = __adis_write_reg;
}
Copy link
Collaborator

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);
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 call should likely be in patch 1?

Copy link
Contributor

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
Copy link
Collaborator

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.

#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)
Copy link
Collaborator

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

goto done;
}

for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) {
Copy link
Collaborator

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;
}
Copy link
Collaborator

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;
Copy link
Collaborator

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)


if (sync_mode >= st->info->num_sync) {
dev_err(dev, "Invalid sync mode: %u for %s\n", sync_mode,
st->info->name);
Copy link
Collaborator

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


ret = devm_add_action_or_reset(dev, adis16550_disable_clk, clk);
if (ret)
return ret;
Copy link
Collaborator

Choose a reason for hiding this comment

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

devm_clk_get_enabled()

Copy link
Contributor

@amiclaus amiclaus left a 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

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.

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;
Copy link
Collaborator

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).

@@ -115,6 +130,7 @@ struct adis {

const struct adis_data *data;
unsigned int burst_extra_len;
const struct adis_ops *ops;
Copy link
Collaborator

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 <[email protected]>
Copy link
Collaborator

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: [email protected]
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml
Copy link
Collaborator

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);
Copy link
Collaborator

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

static void adis16550_debugfs_init(struct iio_dev *indio_dev)
{
}
#endif
Copy link
Collaborator

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 :)

__be32 __din[2], __dout[2];
u16 data = 0;
int ret;
const bool wr = readval ? false : true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need for const...


ret = spi_sync(spi, &msg);
if (ret)
return dev_err_probe(&spi->dev, ret, "Spi failure %d\n", ret);
Copy link
Collaborator

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()

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);
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto

if (crc_rcv != crc)
return dev_err_probe(&adis->spi->dev, -EIO,
"Invalid crc, rcv: 0x%02x, calc: 0x%02x!\n",
crc_rcv, crc);
Copy link
Collaborator

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 <[email protected]>
Signed-off-by: Ramona Gradinariu <[email protected]>
Co-developed-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Nuno Sá <[email protected]>
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 <[email protected]>
Signed-off-by: Ramona Gradinariu <[email protected]>
Co-developed-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Nuno Sá <[email protected]>
Copy link
Contributor

@amiclaus amiclaus left a 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.

rbolboac and others added 4 commits August 28, 2024 14:02
Document the ADIS16550 device devicetree bindings.

Co-developed-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Ramona Gradinariu <[email protected]>
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 <[email protected]>
Signed-off-by: Ramona Gradinariu <[email protected]>
Co-developed-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Nuno Sá <[email protected]>
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 <[email protected]>
Signed-off-by: Antoniu Miclaus <[email protected]>
Signed-off-by: Ramona Gradinariu <[email protected]>
Add entry for the ADIS16550 driver.

Signed-off-by: Ramona Gradinariu <[email protected]>
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.

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,
Copy link
Collaborator

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;
Copy link
Collaborator

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",
Copy link
Collaborator

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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

drop const

break;
}
}

Copy link
Collaborator

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)
Copy link
Collaborator

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));
Copy link
Collaborator

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,
Copy link
Collaborator

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)
Copy link
Collaborator

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;
Copy link
Collaborator

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

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