From: Mike Looijmans <mike.looijmans@topic.nl>
To: Andy Shevchenko <andriy.shevchenko@intel.com>
Cc: jic23@kernel.org, linux-iio@vger.kernel.org, knaack.h@gmx.de,
lars@metafoo.de, pmeerw@pmeerw.net
Subject: Re: [PATCH v4] iio: accel: Add support for the Bosch-Sensortec BMI088
Date: Mon, 23 Mar 2020 13:33:58 +0100 [thread overview]
Message-ID: <35eef6af-bf1f-53e0-56a7-aa8161b4f867@topic.nl> (raw)
In-Reply-To: <20200323113120.GI1922688@smile.fi.intel.com>
On 23-03-2020 12:31, Andy Shevchenko wrote:
> On Mon, Mar 23, 2020 at 10:28:30AM +0100, Mike Looijmans wrote:
>> The BMI088 is a combined module with both accelerometer and gyroscope.
>> This adds the accelerometer driver support for the SPI interface.
>> The gyroscope part is already supported by the BMG160 driver.
>
>
> Thank you, the comment about shared buffer given to v3 still applies.
> Also see below.
>
> ...
>
>> +enum bmi088_accel_axis {
>> + AXIS_X,
>> + AXIS_Y,
>> + AXIS_Z,
>
>> + AXIS_MAX,
>
> If it's a terminator entry, comma is not needed.
Actually it isn't used at all, I'll remove it.
>
>> +};
>
> ...
>
>> +/* Available ODR (output data rates) in Hz */
>> +enum bmi088_odr_modes {
>> + BMI088_ACCEL_MODE_ODR_12_5 = 0x5,
>> + BMI088_ACCEL_MODE_ODR_25 = 0x6,
>> + BMI088_ACCEL_MODE_ODR_50 = 0x7,
>> + BMI088_ACCEL_MODE_ODR_100 = 0x8,
>> + BMI088_ACCEL_MODE_ODR_200 = 0x9,
>> + BMI088_ACCEL_MODE_ODR_400 = 0xa,
>> + BMI088_ACCEL_MODE_ODR_800 = 0xb,
>> + BMI088_ACCEL_MODE_ODR_1600 = 0xc,
>> +};
>
> I'm wondering if you need this enum at all? Only 3 out of 8 are in use, and 25
> of them can be still derived from the 12.5 one.
>
> Maybe replace with comment and ranges?
>
> (But it's up to you, I have no strong opinion here)
Comment and ranges sounds better, it's all power-of-two stuff, and the
values aren't actually being used.
>
> ...
>
>> +static int bmi088_accel_set_power_state(struct bmi088_accel_data *data, bool on)
>> +{
>> + struct device *dev = regmap_get_device(data->regmap);
>> + int ret;
>> +
>> + if (on) {
>> + ret = pm_runtime_get_sync(dev);
>
> if (ret < 0)
> pm_runtime_put_noidle(dev);
>
> See below.
>
>> + } else {
>> + pm_runtime_mark_last_busy(dev);
>> + ret = pm_runtime_put_autosuspend(dev);
>> + }
>> +
>> + if (ret < 0) {
>> + dev_err(dev, "Failed: %s(%d)\n", __func__, on);
>
>> + if (on)
>> + pm_runtime_put_noidle(dev);
>
> Perhaps refactor as above?
>
> In this case it maybe simple...
>
>> +
>> + return ret;
>> + }
>> +
>> + return 0;
>
> ...like this
>
> if (ret < 0)
> dev_err(dev, "Failed: %s(%d)\n", __func__, on);
>
> return ret < 0 ? ret : 0;
>
> (I guess compiler is clever enough to avoid condition twice, but again, I have
> no strong opinion)
As most of the method body depends on that "bool" argument, I would
actually just split it into separate "enable" and "disable" methods.
Simpler to read and understand, and probably doesn't make a difference
in compiled size either.
>
>> +}
>
> ...
>
>> +static int bmi088_accel_enable(struct bmi088_accel_data *data, bool on_off)
>> +{
>> + struct device *dev = regmap_get_device(data->regmap);
>> + int ret;
>> +
>
>> + ret = regmap_write(data->regmap, BMI088_ACCEL_REG_PWR_CTRL,
>> + on_off ? 0x4 : 0x0);
>
> I think
>
> u32 val = on_off ? 0x4 : 0x0;
> ...
> ret = regmap_write(data->regmap, BMI088_ACCEL_REG_PWR_CTRL, val);
>
> will look better.
>
Agree
>
>> + if (ret) {
>> + dev_err(dev, "Error writing ACC_PWR_CTRL reg\n");
>> + return ret;
>> + }
>
>> + return 0;
>> +}
>> +
>> +/* In suspend mode, only the accelerometer is powered down. */
>> +static int bmi088_accel_set_mode(struct bmi088_accel_data *data,
>> + enum bmi088_power_modes mode)
>> +{
>> + struct device *dev = regmap_get_device(data->regmap);
>> + int ret;
>> +
>> + ret = regmap_write(data->regmap, BMI088_ACCEL_REG_PWR_CONF,
>> + mode == BMI088_ACCEL_MODE_SUSPEND ? 0x3 : 0x0);
>
> Ditto.
>
>> + if (ret) {
>> + dev_err(dev, "Error writing ACCEL_PWR_CONF reg\n");
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>
> ...
>
>> +static int bmi088_accel_set_bw(struct bmi088_accel_data *data,
>> + enum bmi088_odr_modes odr_mode,
>> + enum bmi088_osr_modes osr_mode)
>> +{
>> + struct device *dev = regmap_get_device(data->regmap);
>> + int ret;
>> + u8 value = (osr_mode << 4) | (odr_mode & 0xF);
>
> _MASK (GENMASK() + _SHIFT? (See also below)
>
> u8 value = (osr_mode << _SHIFT) | (odr_mode & _MASK);
> int ret;
>
> (note reverse xmas tree ordering)
>
>> +
>> + ret = regmap_write(data->regmap, BMI088_ACCEL_REG_ACC_CONF, value);
>> + if (ret) {
>> + dev_err(dev, "Error writing ACCEL_PWR_CONF reg\n");
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int bmi088_accel_get_sample_freq(struct bmi088_accel_data *data,
>> + int* val, int *val2)
>> +{
>> + unsigned int value;
>> + int ret;
>
>> + value &= 0xf; /* ODR in lower 4 bits */
>
> _MASK? See above.
>
>> + if (value == BMI088_ACCEL_MODE_ODR_12_5) {
>> + *val = 12;
>> + *val2 = 500000;
>> + ret = IIO_VAL_INT_PLUS_MICRO;
>> + } else {
>> + *val = 25 << (value - BMI088_ACCEL_MODE_ODR_25);
>> + *val2 = 0;
>> + ret = IIO_VAL_INT;
>> + }
>> +
>> + return ret;
>> +}
>
> ...
>
>> +
>> +static int bmi088_accel_set_sample_freq(struct bmi088_accel_data *data, int val)
>> +{
>> + unsigned int value = BMI088_ACCEL_MODE_ODR_1600;
>> +
>> + if (val < 12 || val > 1600)
>> + return -EINVAL;
>> +
>
>> + value = fls(val) + (BMI088_ACCEL_MODE_ODR_12_5 - 4);
>
> Wouldn't be
>
> value = fls(val) + 1;
>
> more obvious? Or, perhaps,
>
> roundup_pow_of_two()
>
> ?
>
>> + return regmap_update_bits(data->regmap, BMI088_ACCEL_REG_ACC_CONF,
>> + 0x0f, value);
>
> _MASK ?
>
>> +}
>
>> + if (ret)
>> + return ret;
>> +
>
>> + *val = temp >> 5;
>
> Magic shift.
>
> ...
>
>> + s16 raw_val;
>
>> + ret = regmap_bulk_read(data->regmap,
>> + BMI088_ACCEL_AXIS_TO_REG(chan->scan_index),
>> + data->buffer, 2);
>> + raw_val = get_unaligned_le16(data->buffer);
>
>
> I'm wondering if you can simple use le16_to_cpu()? I guess that buffer is
> always aligned and since you access it always by even addresses, it implies
> aligned access. Applies to other places as well.
>
> ...
>
>> + case IIO_ACCEL:
>
>> + {
>
> Why do you need block?
>
>> + ret = regmap_read(data->regmap,
>> + BMI088_ACCEL_REG_ACC_RANGE, val);
>> + if (ret)
>> + return ret;
>> +
>
>> + *val2 = 15 - (*val & 0x3);
>
> Extra spaces.
>
>> + *val = 3 * 980;
>> +
>> + return IIO_VAL_FRACTIONAL_LOG2;
>> + }
>> + default:
>> + return -EINVAL;
>> + }
>
> ...
>
>> +static const unsigned long bmi088_accel_scan_masks[] = {
>> + BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
>> + 0
>
> + comma or is it agreed value for termination the list?
>
>> +};
>
> ...
>
>
>> + usleep_range(BMI088_ACCEL_MAX_STARTUP_TIME_MS * 1000,
>> + BMI088_ACCEL_MAX_STARTUP_TIME_MS * 1000 * 2);
>
> unsigned long /* or what is used */ sleep = BMI088_ACCEL_MAX_STARTUP_TIME_MS * USEC_PER_MSEC;
> ...
> usleep_range(sleep, 2 * sleep);
>
> ?
>
> ...
>
>> + addr[0] |= 0x80; /* bit7 = RW = '1' */
>
> BIT(7) ?
>
> ...
>
>> +static const struct spi_device_id bmi088_accel_id[] = {
>
>> + {"bmi088_accel", 0},
>
> ', 0' part is not needed.
>
>> + {}
>> +};
>
>
>
>> +++ b/drivers/iio/accel/bmi088-accel.h
>> @@ -0,0 +1,12 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +#ifndef BMI088_ACCEL_H
>> +#define BMI088_ACCEL_H
>> +
>> +extern const struct regmap_config bmi088_regmap_conf;
>> +extern const struct dev_pm_ops bmi088_accel_pm_ops;
>
> Do you need extern?
probably not.
>
>> +int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
>> + const char *name, bool block_supported);
>> +int bmi088_accel_core_remove(struct device *dev);
>
> This needs
>
> #include <linux/types.h>
>
> struct device;
> struct regmap;
>
Hmm, and "struct regmap_config" as well I guess (see above)
--
Mike Looijmans
next prev parent reply other threads:[~2020-03-23 12:34 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-23 9:28 [PATCH v4] iio: accel: Add support for the Bosch-Sensortec BMI088 Mike Looijmans
2020-03-23 11:31 ` Andy Shevchenko
2020-03-23 12:33 ` Mike Looijmans [this message]
2020-03-23 13:47 ` Andy Shevchenko
2020-03-23 13:58 ` Mike Looijmans
2020-03-24 7:38 ` Mike Looijmans
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=35eef6af-bf1f-53e0-56a7-aa8161b4f867@topic.nl \
--to=mike.looijmans@topic.nl \
--cc=andriy.shevchenko@intel.com \
--cc=jic23@kernel.org \
--cc=knaack.h@gmx.de \
--cc=lars@metafoo.de \
--cc=linux-iio@vger.kernel.org \
--cc=pmeerw@pmeerw.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox