[PATCH V10 3/9] iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
Andy Shevchenko
andriy.shevchenko at intel.com
Fri Jun 5 09:08:35 PDT 2026
On Thu, Jun 04, 2026 at 03:18:25PM -0500, Chris Morgan wrote:
> Add the core component of a new inv_icm42607 driver. This includes
> a few setup functions and the full register definition in the
> header file.
...
> +#ifndef INV_ICM42607_H_
> +#define INV_ICM42607_H_
> +
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
I haven't found users for these two.
+ bits.h // BIT() / GENMASK()
> +#include <linux/iio/iio.h>
> +#include <linux/mutex.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
No users for this one.
+ types.h // for bool
...
> +enum inv_icm42607_sensor_mode {
> + INV_ICM42607_SENSOR_MODE_OFF,
> + INV_ICM42607_SENSOR_MODE_STANDBY,
> + INV_ICM42607_SENSOR_MODE_LOW_POWER,
> + INV_ICM42607_SENSOR_MODE_LOW_NOISE,
Are those enums map 1:1 to HW bits or bitfields? If so, assign explicitly each
of them.
> + INV_ICM42607_SENSOR_MODE_NB
Is this a terminator like NUMBER_OF ?
> +};
...
> +/* ODR values */
> +enum inv_icm42607_odr {
> + INV_ICM42607_ODR_1600HZ = 5,
See above. This one is problematic. No one should rely on Linux/C enums when
it's about HW bits. All HW related stuff has to be explicit.
> + INV_ICM42607_ODR_800HZ,
> + INV_ICM42607_ODR_400HZ,
> + INV_ICM42607_ODR_200HZ,
> + INV_ICM42607_ODR_100HZ,
> + INV_ICM42607_ODR_50HZ,
> + INV_ICM42607_ODR_25HZ,
> + INV_ICM42607_ODR_12_5HZ,
> + INV_ICM42607_ODR_6_25HZ_LP,
> + INV_ICM42607_ODR_3_125HZ_LP,
> + INV_ICM42607_ODR_1_5625HZ_LP,
> + INV_ICM42607_ODR_NB
> +};
...
> +struct inv_icm42607_sensor_conf {
> + int mode;
> + int fs;
> + int odr;
> + int filter;
All of them are supposed to be signed? Why?
> +};
...
> +struct inv_icm42607_hw {
> + uint8_t whoami;
What's wrong with u8?
> + const char *name;
> + const struct inv_icm42607_conf *conf;
> +};
...
> +#include <linux/delay.h>
> +#include <linux/dev_printk.h>
> +#include <linux/interrupt.h>
> +#include <linux/iio/iio.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/property.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
IWYU, please.
...
> +/**
> + * inv_icm42607_setup() - check and setup chip
> + * @st: driver internal state
> + * @bus_setup: callback for setting up bus specific registers
> + *
> + * Returns 0 on success, a negative error code otherwise.
If you do kernel-doc, validate it. Return section is missing here.
> + */
...
> +{
> + const struct device *dev = regmap_get_device(st->map);
> + unsigned int val;
> + int ret;
> +
> + ret = regmap_read(st->map, INV_ICM42607_REG_WHOAMI, &val);
> + if (ret)
> + return ret;
> +
> + if (val != st->hw->whoami)
> + dev_warn(dev, "Unknown whoami %#02x expected %#02x (%s)\n",
> + val, st->hw->whoami, st->hw->name);
dev_warn_probe() ?
> + ret = regmap_write(st->map, INV_ICM42607_REG_SIGNAL_PATH_RESET,
> + INV_ICM42607_SIGNAL_PATH_RESET_SOFT_RESET);
> + if (ret)
> + return ret;
> + fsleep(INV_ICM42607_RESET_TIME_MS * 1000);
USEC_PER_MSEC (needs time.h)
> + ret = regmap_read_poll_timeout(st->map, INV_ICM42607_REG_INT_STATUS,
> + val, val & INV_ICM42607_INT_STATUS_RESET_DONE,
> + INV_ICM42607_RESET_TIME_MS * 100,
> + INV_ICM42607_RESET_TIME_MS * 10000);
These are weird, as in the first case it's actually 1/10th of _RESET_TIME_MS.
Perhaps you need to reconsider what you use as that constant. Personally I
prefer to see just plain values with the multipliers (to convert to µs).
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "reset error, reset done bit not set\n");
> +
> + /* Sync the regcache again after a reset. */
> + regcache_mark_dirty(st->map);
> + ret = regcache_sync(st->map);
> + if (ret)
> + return ret;
> +
> + ret = bus_setup(st);
Hmm... This is bad name with potential of name collision in the future (in case
driver bus code wants to have the same name for the function).
> + if (ret)
> + return ret;
> +
> + ret = regmap_set_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
> + INV_ICM42607_INTF_CONFIG0_SENSOR_DATA_ENDIAN);
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
> + INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK,
> + INV_ICM42607_INTF_CONFIG1_CLKSEL_PLL);
> + if (ret)
> + return ret;
> +
> + return inv_icm42607_set_conf(st, st->hw->conf);
> +}
...
> +int inv_icm42607_core_probe(struct regmap *regmap,
> + const struct inv_icm42607_hw *hw,
> + inv_icm42607_bus_setup bus_setup)
> +{
> + struct device *dev = regmap_get_device(regmap);
> + struct inv_icm42607_state *st;
> + int ret;
> +
> + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
> + if (!st)
> + return -ENOMEM;
> +
> + ret = devm_mutex_init(dev, &st->lock);
> + if (ret)
> + return ret;
> +
> + st->hw = hw;
> + st->map = regmap;
> +
> + ret = iio_read_mount_matrix(dev, &st->orientation);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "failed to retrieve mounting matrix %d\n", ret);
Remove duplicate ret printing.
> +
> + ret = devm_regulator_get_enable(dev, "vdd");
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Failed to get vdd regulator\n");
> +
> + st->vddio_supply = devm_regulator_get(dev, "vddio");
> + if (IS_ERR(st->vddio_supply))
> + return dev_err_probe(dev, PTR_ERR(st->vddio_supply),
> + "Failed to get vddio regulator\n");
> +
> + ret = inv_icm42607_enable_vddio_reg(st);
> + if (ret)
> + return ret;
> +
> + ret = devm_add_action_or_reset(dev, inv_icm42607_disable_vddio_reg, st);
> + if (ret)
> + return ret;
> + /* Setup chip registers (includes WHOAMI check, reset check, bus setup) */
> + ret = inv_icm42607_setup(st, bus_setup);
> + if (ret)
> + return ret;
> +
> + return 0;
Just
return inv_icm42607_setup(st, bus_setup);
? Or is it going to be extended in the next changes?
> +}
--
With Best Regards,
Andy Shevchenko
More information about the Linux-rockchip
mailing list