On Mon, Mar 23, 2020 at 8:46 PM Daniel Campello <campello@xxxxxxxxxxxx> wrote: > > Add SEMTECH SX9310/9311 driver. > > The device has the following entry points: > > Usual frequency: > - sampling_frequency > - sampling_frequency_available > > Instant reading of current values for different sensors: > - in_proximity0_raw > - in_proximity1_raw > - in_proximity2_raw > - in_proximity3_comb_raw > and associated events in events/ ... > +#include <linux/acpi.h> > +#include <linux/of.h> No users for these (see ID table handling below), but property.h would be needed. ... > +#define SX9310_EVENT_IRQ (SX9310_FAR_IRQ | \ > + SX9310_CLOSE_IRQ) Better formatting is #define FOO \ (BAR | ZOO) ... > +struct sx9310_data { > + struct i2c_client *client; Do you really need client? Perhaps struct device will be enough? > + struct iio_trigger *trig; > + struct regmap *regmap; > + /* > + * Last reading of the proximity status for each channel. > + * We only send an event to user space when this changes. > + */ > + bool prox_stat[SX9310_NUM_CHANNELS]; > + bool trigger_enabled; > + __be16 buffer[SX9310_NUM_CHANNELS + > + 4]; /* 64-bit data + 64-bit timestamp */ Please, fix formatting. > +}; ... > +static int sx9310_update_chan_en(struct sx9310_data *data, > + unsigned int chan_read, > + unsigned int chan_event) > +{ > + int ret; > + > + if ((data->chan_read | data->chan_event) != (chan_read | chan_event)) { > + ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL0, > + SX9310_CHAN_ENABLED_MASK, > + chan_read | chan_event); unsigned int readevent = chan_read | chan_event; ... if (... != readevent) { ..., readevent); } > + if (ret) > + return ret; > + } > + data->chan_read = chan_read; > + data->chan_event = chan_event; > + return 0; > +} ... > +static int sx9310_read_prox_data(struct sx9310_data *data, > + const struct iio_chan_spec *chan, __be16 *val) > +{ > + int ret; > + > + ret = regmap_write(data->regmap, SX9310_REG_SENSOR_SEL, chan->channel); > + if (ret < 0) > + return ret; > + > + return regmap_bulk_read(data->regmap, chan->address, val, 2); sizeof()? > +} ... > + if (data->client->irq > 0) { > + ret = wait_for_completion_interruptible(&data->completion); > + reinit_completion(&data->completion); Logically reinit better to be called before you start measurement. > + } else { > + ret = sx9310_wait_for_sample(data); > + } ... > + *val = sign_extend32(be16_to_cpu(rawval), > + (chan->address == SX9310_REG_DIFF_MSB ? 11 : 15)); Too many parentheses. ... > + mutex_lock(&data->mutex); > + > + ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL0, > + SX9310_SCAN_PERIOD_MASK, > + i << SX9310_SCAN_PERIOD_SHIFT); > + > + mutex_unlock(&data->mutex); Btw, can you use locking provided by regmap? ... > + /* > + * Even if no event is enabled, we need to wake the thread to > + * clear the interrupt state by reading SX9310_REG_IRQ_SRC. It Move it to the next line. > + * is not possible to do that here because regmap_read takes a > + * mutex. > + */ ... > + for (chan = 0; chan < SX9310_NUM_CHANNELS; chan++) { > + int dir; > + u64 ev; > + bool new_prox = val & BIT(chan); > + > + if (!(data->chan_event & BIT(chan))) > + continue; for_each_set_bit() > + if (new_prox == data->prox_stat[chan]) > + /* No change on this channel. */ > + continue; > + } ... > +static struct attribute *sx9310_attributes[] = { > + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, > + NULL, Comma is not needed for terminator. > +}; ... > +static int sx9310_buffer_preenable(struct iio_dev *indio_dev) > +{ > + struct sx9310_data *data = iio_priv(indio_dev); > + unsigned int channels = 0; > + int bit, ret; > + > + mutex_lock(&data->mutex); > + for_each_set_bit(bit, indio_dev->active_scan_mask, > + indio_dev->masklength) > + channels |= BIT(indio_dev->channels[bit].channel); unsigned long channels; ... __set_bit(...); > + ret = sx9310_update_chan_en(data, channels, data->chan_event); > + mutex_unlock(&data->mutex); > + return ret; > +} ... > +#define SX_INIT(_reg, _def) \ > + { \ > + .reg = SX9310_REG_##_reg, \ > + .def = _def, \ > + } Usually it's a good tone to #undef custom macro when they are not needed anymore. ... > + for (i = 100; i >= 0; i--) { > + msleep(20); > + ret = regmap_read(data->regmap, SX9310_REG_STAT1, &val); > + if (ret < 0) > + goto out; > + if (!(val & SX9310_COMPSTAT_MASK)) > + break; > + } NIH of regmap_real_poll_timeout(); > + > + if (i < 0) { > + dev_err(&data->client->dev, > + "initial compensation timed out: 0x%02x", val); > + ret = -ETIMEDOUT; > + } ... > + ret = regmap_write(data->regmap, initval->reg, initval->def); > + if (ret < 0) Do you need all these ' < 0'? > + return ret; ... > + const struct acpi_device_id *acpi_id; > + /* id will be NULL when enumerated via ACPI */ > + if (id) { > + if (id->driver_data != whoami) > + dev_err(dev, "WHOAMI does not match i2c_device_id: %s", > + id->name); > + } else if (ACPI_HANDLE(dev)) { > + acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); > + if (!acpi_id) > + return -ENODEV; > + if (acpi_id->driver_data != whoami) > + dev_err(dev, "WHOAMI does not match acpi_device_id: %s", > + acpi_id->id); > + } else > + return -ENODEV; device_get_match_data(). ... > +static int sx9310_probe(struct i2c_client *client, > + const struct i2c_device_id *id) Can you switch to ->probe_new()? ... > + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); > + if (indio_dev == NULL) if (!indio_dev) > + return -ENOMEM; ... > + dev_err(&client->dev, "error in reading WHOAMI register: %d", > + ret); If you introduce temporary variable the code will be better to read struct device *dev = &client->dev; > + ret = sx9310_set_indio_dev_name(&client->dev, indio_dev, id, > + data->whoami); > + if (ret < 0) > + return ret; ... > +static const struct acpi_device_id sx9310_acpi_match[] = { > + { "STH9310", SX9310_WHOAMI_VALUE }, > + { "STH9311", SX9311_WHOAMI_VALUE }, Hmm... May I ask some official proof that these IDs are real and issued by vendor? > + {}, No comma. > +}; > +MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match); > +static const struct of_device_id sx9310_of_match[] = { > + { .compatible = "semtech,sx9310" }, > + { .compatible = "semtech,sx9311" }, > + {}, No comma. > +}; > +MODULE_DEVICE_TABLE(of, sx9310_of_match); > + > +static const struct i2c_device_id sx9310_id[] = { > + { "sx9310", SX9310_WHOAMI_VALUE }, > + { "sx9311", SX9311_WHOAMI_VALUE }, > + {}, No comma. > +}; > +MODULE_DEVICE_TABLE(i2c, sx9310_id); ... > + .acpi_match_table = ACPI_PTR(sx9310_acpi_match), > + .of_match_table = of_match_ptr(sx9310_of_match), Drop these macros. You probably didn't test with !ACPI and/or !OF -- should be compiler warning. > + .pm = &sx9310_pm_ops, > + }, -- With Best Regards, Andy Shevchenko