On Tue, Mar 24, 2020 at 10:18 AM Andy Shevchenko <andy.shevchenko@xxxxxxxxx> wrote: > > 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. > > I removed of.h but kept acpi.h in v6 since it was needed for other ACPI macros on the probe function > > ... > > > +#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? There are references to client->irq in some places > > > > + 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. > I think this is effectively before measurement, minus error/locking handling. > > + } 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? The lock is protecting critical sections that include multiple regmap and other operations together in other parts of the code. > > > ... > > > + /* > > + * 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() Thanks, more clear now! > > > > + 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(); Sorry, somehow I overlooked this on v6, I'll send v7 with it > > > > + > > + 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'? Not sure what do you mean? This one in particular is trying to fail fast the probe > > > > + 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(). > THANKS! I was happy to learn about this after you pointed it out! > > ... > > > +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? Not sure how to prove this but they are live in device firmware right now. One example: https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/b905beb46935c114ebc416583bb2e5407183af35/src/mainboard/google/zoombini/variants/meowth/devicetree.cb > > > > + {}, > > 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. Why do we want to drop these? I tried compiling with either and both disabled and did not see a warning on my system. > > > > + .pm = &sx9310_pm_ops, > > + }, > > -- > With Best Regards, > Andy Shevchenko Thanks for the review. Sorry for the delay on this email after sending v6. Regards, Daniel