diff options
Diffstat (limited to 'drivers/iio/light')
32 files changed, 729 insertions, 543 deletions
diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c index 633a105fd7f0..0ea282ecc99a 100644 --- a/drivers/iio/light/adux1020.c +++ b/drivers/iio/light/adux1020.c @@ -808,10 +808,8 @@ static int adux1020_probe(struct i2c_client *client) NULL, adux1020_interrupt_handler, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, ADUX1020_DRV_NAME, indio_dev); - if (ret) { - dev_err(&client->dev, "irq request error %d\n", -ret); + if (ret) return ret; - } } return devm_iio_device_register(&client->dev, indio_dev); diff --git a/drivers/iio/light/apds9160.c b/drivers/iio/light/apds9160.c index 8dacb1730429..d7e0924b8106 100644 --- a/drivers/iio/light/apds9160.c +++ b/drivers/iio/light/apds9160.c @@ -1545,11 +1545,8 @@ static int apds9160_probe(struct i2c_client *client) apds9160_irq_handler, IRQF_ONESHOT, "apds9160_event", indio_dev); - if (ret) { - return dev_err_probe(dev, ret, - "request irq (%d) failed\n", - client->irq); - } + if (ret) + return ret; } else { indio_dev->info = &apds9160_info_no_events; indio_dev->channels = apds9160_channels_without_events; diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c index d60ade1209f3..f0abbc4a862a 100644 --- a/drivers/iio/light/apds9300.c +++ b/drivers/iio/light/apds9300.c @@ -432,10 +432,8 @@ static int apds9300_probe(struct i2c_client *client) NULL, apds9300_interrupt_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "apds9300_event", indio_dev); - if (ret) { - dev_err(&client->dev, "irq request error %d\n", -ret); + if (ret) goto err; - } } ret = iio_device_register(indio_dev); diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c index 5ca4c87524fe..f681b02e4922 100644 --- a/drivers/iio/light/apds9306.c +++ b/drivers/iio/light/apds9306.c @@ -469,9 +469,9 @@ static int apds9306_read_data(struct apds9306_data *data, int *val, int reg) int status = 0; u8 buff[3]; - ret = pm_runtime_resume_and_get(data->dev); - if (ret) - return ret; + PM_RUNTIME_ACQUIRE_AUTOSUSPEND(data->dev, pm); + if (PM_RUNTIME_ACQUIRE_ERR(&pm)) + return PM_RUNTIME_ACQUIRE_ERR(&pm); ret = regmap_field_read(rf->intg_time, &intg_time_idx); if (ret) @@ -535,8 +535,6 @@ static int apds9306_read_data(struct apds9306_data *data, int *val, int reg) *val = get_unaligned_le24(&buff); - pm_runtime_put_autosuspend(data->dev); - return 0; } @@ -1286,8 +1284,7 @@ static int apds9306_probe(struct i2c_client *client) apds9306_irq_handler, IRQF_ONESHOT, "apds9306_event", indio_dev); if (ret) - return dev_err_probe(dev, ret, - "failed to assign interrupt.\n"); + return ret; } else { indio_dev->info = &apds9306_info_no_events; indio_dev->channels = apds9306_channels_without_events; diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index 2686c3b0c03b..afe520de60e2 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1098,10 +1098,8 @@ static int apds9960_probe(struct i2c_client *client) IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "apds9960_event", indio_dev); - if (ret) { - dev_err(&client->dev, "request irq (%d) failed\n", client->irq); + if (ret) goto error_power_down; - } ret = iio_device_register(indio_dev); if (ret) diff --git a/drivers/iio/light/bh1745.c b/drivers/iio/light/bh1745.c index 0aa8e5cc6c56..2b8ff36071b8 100644 --- a/drivers/iio/light/bh1745.c +++ b/drivers/iio/light/bh1745.c @@ -784,8 +784,7 @@ static int bh1745_setup_triggered_buffer(struct iio_dev *indio_dev, IRQF_ONESHOT, "bh1745_interrupt", indio_dev); if (ret) - return dev_err_probe(dev, ret, - "Request for IRQ failed\n"); + return ret; } return 0; diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index 2590fc8fd154..b32a94028f09 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -368,7 +368,7 @@ static int cm32181_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: cm32181->calibscale = val; - return val; + return 0; case IIO_CHAN_INFO_INT_TIME: ret = cm32181_write_als_it(cm32181, val2); return ret; diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index fbb9e0a13733..506c91f44f43 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -80,22 +80,19 @@ static int cm3323_init(struct iio_dev *indio_dev) { int ret; struct cm3323_data *data = iio_priv(indio_dev); + struct device *dev = &data->client->dev; ret = i2c_smbus_read_word_data(data->client, CM3323_CMD_CONF); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_conf\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Error reading reg_conf\n"); /* enable sensor and set auto force mode */ ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT); data->reg_conf = ret; ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, data->reg_conf); - if (ret < 0) { - dev_err(&data->client->dev, "Error writing reg_conf\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Error writing reg_conf\n"); return 0; } @@ -236,10 +233,8 @@ static int cm3323_probe(struct i2c_client *client) indio_dev->modes = INDIO_DIRECT_MODE; ret = cm3323_init(indio_dev); - if (ret < 0) { - dev_err(&client->dev, "cm3323 chip init failed\n"); + if (ret < 0) return ret; - } ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev); if (ret < 0) diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c index 98c84f33db60..34c127593947 100644 --- a/drivers/iio/light/cm3605.c +++ b/drivers/iio/light/cm3605.c @@ -232,10 +232,8 @@ static int cm3605_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, irq, cm3605_prox_irq, NULL, 0, "cm3605", indio_dev); - if (ret) { - dev_err(dev, "unable to request IRQ\n"); + if (ret) goto out_disable_aset; - } /* Just name the trigger the same as the driver */ led_trigger_register_simple("cm3605", &cm3605->led); @@ -324,3 +322,4 @@ module_platform_driver(cm3605_driver); MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); MODULE_DESCRIPTION("CM3605 ambient light and proximity sensor driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_CONSUMER"); diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index a8db514cca5e..1fd40d60182e 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -342,6 +342,10 @@ static int gp2ap002_write_event_config(struct iio_dev *indio_dev, bool state) { struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); + int ret; + + if (state == gp2ap002->enabled) + return 0; if (state) { /* @@ -349,13 +353,16 @@ static int gp2ap002_write_event_config(struct iio_dev *indio_dev, * already) and reintialize the sensor by using runtime_pm * callbacks. */ - pm_runtime_get_sync(gp2ap002->dev); - gp2ap002->enabled = true; + ret = pm_runtime_resume_and_get(gp2ap002->dev); + if (ret) + return ret; + } else { pm_runtime_put_autosuspend(gp2ap002->dev); - gp2ap002->enabled = false; } + gp2ap002->enabled = state; + return 0; } @@ -573,10 +580,8 @@ static int gp2ap002_probe(struct i2c_client *client) ret = devm_request_threaded_irq(dev, client->irq, NULL, gp2ap002_prox_irq, IRQF_ONESHOT, "gp2ap002", indio_dev); - if (ret) { - dev_err(dev, "unable to request IRQ\n"); + if (ret) goto out_put_pm; - } gp2ap002->irq = client->irq; /* @@ -642,6 +647,7 @@ static int gp2ap002_runtime_suspend(struct device *dev) /* Disable chip and IRQ, everything off */ ret = regmap_write(gp2ap002->map, GP2AP002_OPMOD, 0x00); if (ret) { + enable_irq(gp2ap002->irq); dev_err(gp2ap002->dev, "error setting up operation mode\n"); return ret; } @@ -669,7 +675,7 @@ static int gp2ap002_runtime_resume(struct device *dev) ret = regulator_enable(gp2ap002->vio); if (ret) { dev_err(dev, "failed to enable VIO regulator in resume path\n"); - return ret; + goto out_disable_vdd; } msleep(20); @@ -677,13 +683,19 @@ static int gp2ap002_runtime_resume(struct device *dev) ret = gp2ap002_init(gp2ap002); if (ret) { dev_err(dev, "re-initialization failed\n"); - return ret; + goto out_disable_vio; } /* Re-activate the IRQ */ enable_irq(gp2ap002->irq); return 0; + +out_disable_vio: + regulator_disable(gp2ap002->vio); +out_disable_vdd: + regulator_disable(gp2ap002->vdd); + return ret; } static DEFINE_RUNTIME_DEV_PM_OPS(gp2ap002_dev_pm_ops, gp2ap002_runtime_suspend, @@ -717,3 +729,4 @@ module_i2c_driver(gp2ap002_driver); MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); MODULE_DESCRIPTION("GP2AP002 ambient light and proximity sensor driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS("IIO_CONSUMER"); diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 6bf1bc9a38fe..929343e42d83 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -33,9 +33,9 @@ struct als_state { u32 illum[CHANNEL_SCAN_INDEX_MAX]; aligned_s64 timestamp; } scan; - int scale_pre_decml; - int scale_post_decml; - int scale_precision; + int scale_pre_decml[CHANNEL_SCAN_INDEX_MAX]; + int scale_post_decml[CHANNEL_SCAN_INDEX_MAX]; + int scale_precision[CHANNEL_SCAN_INDEX_MAX]; int value_offset; int num_channels; s64 timestamp; @@ -119,9 +119,8 @@ static const struct iio_chan_spec als_channels[] = { /* Channel read_raw handler */ static int als_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) { struct als_state *als_state = iio_priv(indio_dev); struct hid_sensor_hub_device *hsdev = als_state->common_attributes.hsdev; @@ -162,12 +161,12 @@ static int als_read_raw(struct iio_dev *indio_dev, } if (report_id >= 0) { hid_sensor_power_state(&als_state->common_attributes, - true); + true); *val = sensor_hub_input_attr_get_raw_value( hsdev, hsdev->usage, address, report_id, SENSOR_HUB_SYNC, min < 0); hid_sensor_power_state(&als_state->common_attributes, - false); + false); } else { *val = 0; return -EINVAL; @@ -175,9 +174,11 @@ static int als_read_raw(struct iio_dev *indio_dev, ret_type = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - *val = als_state->scale_pre_decml; - *val2 = als_state->scale_post_decml; - ret_type = als_state->scale_precision; + if (chan->scan_index >= CHANNEL_SCAN_INDEX_MAX) + return -EINVAL; + *val = als_state->scale_pre_decml[chan->scan_index]; + *val2 = als_state->scale_post_decml[chan->scan_index]; + ret_type = als_state->scale_precision[chan->scan_index]; break; case IIO_CHAN_INFO_OFFSET: *val = als_state->value_offset; @@ -205,10 +206,8 @@ static int als_read_raw(struct iio_dev *indio_dev, /* Channel write_raw handler */ static int als_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct als_state *als_state = iio_priv(indio_dev); int ret = 0; @@ -240,8 +239,7 @@ static const struct iio_info als_info = { /* Callback handler to send event after all samples are received and captured */ static int als_proc_event(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - void *priv) + u32 usage_id, void *priv) { struct iio_dev *indio_dev = platform_get_drvdata(priv); struct als_state *als_state = iio_priv(indio_dev); @@ -262,9 +260,9 @@ static int als_proc_event(struct hid_sensor_hub_device *hsdev, /* Capture samples in local storage */ static int als_capture_sample(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - size_t raw_len, char *raw_data, - void *priv) + u32 usage_id, + size_t raw_len, char *raw_data, + void *priv) { struct iio_dev *indio_dev = platform_get_drvdata(priv); struct als_state *als_state = iio_priv(indio_dev); @@ -303,9 +301,9 @@ static int als_capture_sample(struct hid_sensor_hub_device *hsdev, /* Parse report which is specific to an usage id*/ static int als_parse_report(struct platform_device *pdev, - struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - struct als_state *st) + struct hid_sensor_hub_device *hsdev, + u32 usage_id, + struct als_state *st) { struct iio_chan_spec *channels; int ret, index = 0; @@ -331,6 +329,10 @@ static int als_parse_report(struct platform_device *pdev, }; ++index; + st->scale_precision[i] = hid_sensor_format_scale(usage_id, + &st->als[i], &st->scale_pre_decml[i], + &st->scale_post_decml[i]); + dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index, st->als[i].report_id); } @@ -340,10 +342,6 @@ static int als_parse_report(struct platform_device *pdev, if (index) ret = 0; - st->scale_precision = hid_sensor_format_scale(usage_id, - &st->als[CHANNEL_SCAN_INDEX_INTENSITY], - &st->scale_pre_decml, &st->scale_post_decml); - return ret; } @@ -399,31 +397,31 @@ static int hid_als_probe(struct platform_device *pdev) atomic_set(&als_state->common_attributes.data_ready, 0); ret = hid_sensor_setup_trigger(indio_dev, name, - &als_state->common_attributes); + &als_state->common_attributes); if (ret < 0) { dev_err(&pdev->dev, "trigger setup failed\n"); return ret; } - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&pdev->dev, "device register failed\n"); - goto error_remove_trigger; - } - als_state->callbacks.send_event = als_proc_event; als_state->callbacks.capture_sample = als_capture_sample; als_state->callbacks.pdev = pdev; ret = sensor_hub_register_callback(hsdev, hsdev->usage, &als_state->callbacks); if (ret < 0) { dev_err(&pdev->dev, "callback reg failed\n"); - goto error_iio_unreg; + goto error_remove_trigger; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "device register failed\n"); + goto error_remove_callback; } return ret; -error_iio_unreg: - iio_device_unregister(indio_dev); +error_remove_callback: + sensor_hub_remove_callback(hsdev, hsdev->usage); error_remove_trigger: hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); return ret; @@ -436,8 +434,8 @@ static void hid_als_remove(struct platform_device *pdev) struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct als_state *als_state = iio_priv(indio_dev); - sensor_hub_remove_callback(hsdev, hsdev->usage); iio_device_unregister(indio_dev); + sensor_hub_remove_callback(hsdev, hsdev->usage); hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); } diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 95bf2bfd86ee..63fd3eff171c 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -69,9 +69,8 @@ static const struct iio_chan_spec prox_channels[] = { /* Channel read_raw handler */ static int prox_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) { struct prox_state *prox_state = iio_priv(indio_dev); struct hid_sensor_hub_device *hsdev; @@ -134,10 +133,8 @@ static int prox_read_raw(struct iio_dev *indio_dev, /* Channel write_raw handler */ static int prox_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct prox_state *prox_state = iio_priv(indio_dev); int ret = 0; @@ -165,8 +162,7 @@ static const struct iio_info prox_info = { /* Callback handler to send event after all samples are received and captured */ static int prox_proc_event(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - void *priv) + u32 usage_id, void *priv) { struct iio_dev *indio_dev = platform_get_drvdata(priv); struct prox_state *prox_state = iio_priv(indio_dev); @@ -182,9 +178,9 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev, /* Capture samples in local storage */ static int prox_capture_sample(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, - size_t raw_len, char *raw_data, - void *priv) + u32 usage_id, + size_t raw_len, char *raw_data, + void *priv) { struct iio_dev *indio_dev = platform_get_drvdata(priv); struct prox_state *prox_state = iio_priv(indio_dev); @@ -217,8 +213,8 @@ static int prox_capture_sample(struct hid_sensor_hub_device *hsdev, /* Parse report which is specific to an usage id*/ static int prox_parse_report(struct platform_device *pdev, - struct hid_sensor_hub_device *hsdev, - struct prox_state *st) + struct hid_sensor_hub_device *hsdev, + struct prox_state *st) { struct iio_chan_spec *channels = st->channels; int index = 0; @@ -270,8 +266,7 @@ static int hid_prox_probe(struct platform_device *pdev) struct iio_dev *indio_dev; struct prox_state *prox_state; - indio_dev = devm_iio_device_alloc(&pdev->dev, - sizeof(struct prox_state)); + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct prox_state)); if (!indio_dev) return -ENOMEM; platform_set_drvdata(pdev, indio_dev); @@ -305,18 +300,12 @@ static int hid_prox_probe(struct platform_device *pdev) atomic_set(&prox_state->common_attributes.data_ready, 0); ret = hid_sensor_setup_trigger(indio_dev, name, - &prox_state->common_attributes); + &prox_state->common_attributes); if (ret) { dev_err(&pdev->dev, "trigger setup failed\n"); return ret; } - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&pdev->dev, "device register failed\n"); - goto error_remove_trigger; - } - prox_state->callbacks.send_event = prox_proc_event; prox_state->callbacks.capture_sample = prox_capture_sample; prox_state->callbacks.pdev = pdev; @@ -324,13 +313,19 @@ static int hid_prox_probe(struct platform_device *pdev) &prox_state->callbacks); if (ret < 0) { dev_err(&pdev->dev, "callback reg failed\n"); - goto error_iio_unreg; + goto error_remove_trigger; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "device register failed\n"); + goto error_remove_callback; } return ret; -error_iio_unreg: - iio_device_unregister(indio_dev); +error_remove_callback: + sensor_hub_remove_callback(hsdev, hsdev->usage); error_remove_trigger: hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes); return ret; @@ -343,8 +338,8 @@ static void hid_prox_remove(struct platform_device *pdev) struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct prox_state *prox_state = iio_priv(indio_dev); - sensor_hub_remove_callback(hsdev, hsdev->usage); iio_device_unregister(indio_dev); + sensor_hub_remove_callback(hsdev, hsdev->usage); hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes); } diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index b88e7c4eae3e..33deb1726689 100644 --- a/drivers/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -333,16 +333,6 @@ static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data) return isl29028_read_als_ir(chip, ir_data); } -static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on) -{ - struct device *dev = regmap_get_device(chip->regmap); - - if (on) - return pm_runtime_resume_and_get(dev); - - return pm_runtime_put_autosuspend(dev); -} - /* Channel IO */ static int isl29028_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -352,7 +342,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev, struct device *dev = regmap_get_device(chip->regmap); int ret; - ret = isl29028_set_pm_runtime_busy(chip, true); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret; @@ -405,11 +395,11 @@ static int isl29028_write_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; - ret = isl29028_set_pm_runtime_busy(chip, false); + ret = pm_runtime_put_autosuspend(dev); if (ret < 0) return ret; - return ret; + return 0; } static int isl29028_read_raw(struct iio_dev *indio_dev, @@ -420,7 +410,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, struct device *dev = regmap_get_device(chip->regmap); int ret, pm_ret; - ret = isl29028_set_pm_runtime_busy(chip, true); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret; @@ -476,10 +466,10 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, /** * Preserve the ret variable if the call to - * isl29028_set_pm_runtime_busy() is successful so the reading + * pm_runtime_put_autosuspend() is successful so the reading * (if applicable) is returned to user space. */ - pm_ret = isl29028_set_pm_runtime_busy(chip, false); + pm_ret = pm_runtime_put_autosuspend(dev); if (pm_ret < 0) return pm_ret; diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c index bdc74b8226c8..bc031f2c3141 100644 --- a/drivers/iio/light/ltr390.c +++ b/drivers/iio/light/ltr390.c @@ -838,8 +838,7 @@ static int ltr390_probe(struct i2c_client *client) "ltr390_thresh_event", indio_dev); if (ret) - return dev_err_probe(dev, ret, - "request irq (%d) failed\n", client->irq); + return ret; } ret = ltr390_pm_init(data); diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 7d045be78c6d..fa0d16890c8b 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -1537,11 +1537,8 @@ static int ltr501_probe(struct i2c_client *client) IRQF_ONESHOT, "ltr501_thresh_event", indio_dev); - if (ret) { - dev_err(&client->dev, "request irq (%d) failed\n", - client->irq); + if (ret) return ret; - } } else { indio_dev->info = data->chip_info->info_no_irq; } diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c index 3f34ddc911b4..0a8851342039 100644 --- a/drivers/iio/light/ltrf216a.c +++ b/drivers/iio/light/ltrf216a.c @@ -247,11 +247,10 @@ static int ltrf216a_get_lux(struct ltrf216a_data *data) return ret; greendata = ltrf216a_read_data(data, LTRF216A_ALS_DATA_0); + ltrf216a_set_power_state(data, false); if (greendata < 0) return greendata; - ltrf216a_set_power_state(data, false); - lux = greendata * data->info->lux_multiplier * LTRF216A_WIN_FAC; return lux; diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index c5bd7fa23fb7..a948353014ac 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -10,6 +10,7 @@ #include <linux/array_size.h> #include <linux/bits.h> +#include <linux/cleanup.h> #include <linux/delay.h> #include <linux/dev_printk.h> #include <linux/errno.h> @@ -100,9 +101,14 @@ struct opt3001_chip_info { struct opt3001 { struct i2c_client *client; - struct device *dev; + /* + * Ensure data capture and read-modify-write sequences are + * not interrupted. + */ struct mutex lock; + + /* Allows for IRQs to bypass locking mechanism */ bool ok_to_ignore_lock; bool result_ready; wait_queue_head_t result_ready_queue; @@ -223,11 +229,10 @@ static const struct opt3001_scale opt3002_scales[] = { }, }; -static int opt3001_find_scale(const struct opt3001 *opt, int val, - int val2, u8 *exponent) +static int opt3001_find_scale(const struct opt3001 *opt, int val, int val2, + u8 *exponent) { - int i; - for (i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) { const struct opt3001_scale *scale = &(*opt->chip_info->scales)[i]; /* * Compare the integer and micro parts to determine value scale. @@ -242,8 +247,8 @@ static int opt3001_find_scale(const struct opt3001 *opt, int val, return -EINVAL; } -static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent, - u16 mantissa, int *val, int *val2) +static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent, u16 mantissa, + int *val, int *val2) { int ret; int whole = opt->chip_info->factor_whole; @@ -310,123 +315,143 @@ static const struct iio_chan_spec opt3002_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(1), }; -static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2) +static int opt3001_start_conversion(struct opt3001 *opt) { - int ret; - u16 mantissa; + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; u16 reg; - u8 exponent; - u16 value; - long timeout; - - if (opt->use_irq) { - /* - * Enable the end-of-conversion interrupt mechanism. Note that - * doing so will overwrite the low-level limit value however we - * will restore this value later on. - */ - ret = i2c_smbus_write_word_swapped(opt->client, - OPT3001_LOW_LIMIT, - OPT3001_LOW_LIMIT_EOC_ENABLE); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; - } - - /* Allow IRQ to access the device despite lock being set */ - opt->ok_to_ignore_lock = true; - } + int ret; /* Reset data-ready indicator flag */ opt->result_ready = false; /* Configure for single-conversion mode and start a new conversion */ - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); - goto err; + dev_err(dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + return ret; } reg = ret; opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SINGLE); - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION, - reg); + ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg); + if (ret) + dev_err(dev, "failed to write register %02x\n", + OPT3001_CONFIGURATION); + + return ret; +} + +static int opt3001_get_processed_irq(struct opt3001 *opt) +{ + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; + u16 value; + int ret; + + /* + * Enable the end-of-conversion interrupt mechanism. Note that doing so + * will overwrite the low-level limit value however we will restore this + * value later on. + */ + ret = i2c_smbus_write_word_swapped(client, + OPT3001_LOW_LIMIT, + OPT3001_LOW_LIMIT_EOC_ENABLE); if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_CONFIGURATION); - goto err; + dev_err(dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + return ret; } - if (opt->use_irq) { - /* Wait for the IRQ to indicate the conversion is complete */ - ret = wait_event_timeout(opt->result_ready_queue, - opt->result_ready, - msecs_to_jiffies(OPT3001_RESULT_READY_LONG)); - if (ret == 0) { - ret = -ETIMEDOUT; - goto err; - } - } else { - /* Sleep for result ready time */ - timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ? - OPT3001_RESULT_READY_SHORT : OPT3001_RESULT_READY_LONG; - msleep(timeout); - - /* Check result ready flag */ - ret = i2c_smbus_read_word_swapped(opt->client, - OPT3001_CONFIGURATION); - if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); - goto err; - } + /* Allow IRQ to access the device despite lock being set */ + opt->ok_to_ignore_lock = true; - if (!(ret & OPT3001_CONFIGURATION_CRF)) { - ret = -ETIMEDOUT; - goto err; - } + ret = opt3001_start_conversion(opt); + if (ret) + goto err; - /* Obtain value */ - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT); - if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_RESULT); - goto err; - } - opt->result = ret; - opt->result_ready = true; - } + if (wait_event_timeout(opt->result_ready_queue, opt->result_ready, + msecs_to_jiffies(OPT3001_RESULT_READY_LONG))) + ret = 0; + else + ret = -ETIMEDOUT; err: - if (opt->use_irq) - /* Disallow IRQ to access the device while lock is active */ - opt->ok_to_ignore_lock = false; + opt->ok_to_ignore_lock = false; if (ret < 0) return ret; - if (opt->use_irq) { - /* - * Disable the end-of-conversion interrupt mechanism by - * restoring the low-level limit value (clearing - * OPT3001_LOW_LIMIT_EOC_ENABLE). Note that selectively clearing - * those enable bits would affect the actual limit value due to - * bit-overlap and therefore can't be done. - */ - value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; - ret = i2c_smbus_write_word_swapped(opt->client, - OPT3001_LOW_LIMIT, - value); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; - } + /* + * Disable the end-of-conversion interrupt mechanism by restoring the + * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note + * that selectively clearing those enable bits would affect the actual + * limit value due to bit-overlap and therefore can't be done. + */ + value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; + ret = i2c_smbus_write_word_swapped(client, OPT3001_LOW_LIMIT, value); + if (ret) + dev_err(dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + + return ret; +} + +static int opt3001_get_processed_noirq(struct opt3001 *opt) +{ + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; + int ret; + + ret = opt3001_start_conversion(opt); + if (ret) + return ret; + + if (opt->int_time == OPT3001_INT_TIME_SHORT) + msleep(OPT3001_RESULT_READY_SHORT); + else + msleep(OPT3001_RESULT_READY_LONG); + + /* Check result ready flag */ + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); + if (ret < 0) { + dev_err(dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + return ret; } + if (!(ret & OPT3001_CONFIGURATION_CRF)) + return -ETIMEDOUT; + + /* Obtain value */ + ret = i2c_smbus_read_word_swapped(client, OPT3001_RESULT); + if (ret < 0) { + dev_err(dev, "failed to read register %02x\n", + OPT3001_RESULT); + return ret; + } + + opt->result = ret; + opt->result_ready = true; + + return 0; +} + +static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2) +{ + u16 mantissa; + u8 exponent; + int ret; + + if (opt->use_irq) + ret = opt3001_get_processed_irq(opt); + else + ret = opt3001_get_processed_noirq(opt); + if (ret) + return ret; + exponent = OPT3001_REG_EXPONENT(opt->result); mantissa = OPT3001_REG_MANTISSA(opt->result); @@ -445,13 +470,15 @@ static int opt3001_get_int_time(struct opt3001 *opt, int *val, int *val2) static int opt3001_set_int_time(struct opt3001 *opt, int time) { + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; int ret; u16 reg; - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); + dev_err(dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); return ret; } @@ -470,16 +497,14 @@ static int opt3001_set_int_time(struct opt3001 *opt, int time) return -EINVAL; } - return i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION, - reg); + return i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg); } static int opt3001_read_raw(struct iio_dev *iio, - struct iio_chan_spec const *chan, int *val, int *val2, - long mask) + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) { struct opt3001 *opt = iio_priv(iio); - int ret; if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS) return -EBUSY; @@ -487,31 +512,24 @@ static int opt3001_read_raw(struct iio_dev *iio, if (chan->type != opt->chip_info->chan_type) return -EINVAL; - mutex_lock(&opt->lock); + guard(mutex)(&opt->lock); switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: - ret = opt3001_get_processed(opt, val, val2); - break; + return opt3001_get_processed(opt, val, val2); case IIO_CHAN_INFO_INT_TIME: - ret = opt3001_get_int_time(opt, val, val2); - break; + return opt3001_get_int_time(opt, val, val2); default: - ret = -EINVAL; + return -EINVAL; } - - mutex_unlock(&opt->lock); - - return ret; } static int opt3001_write_raw(struct iio_dev *iio, - struct iio_chan_spec const *chan, int val, int val2, - long mask) + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct opt3001 *opt = iio_priv(iio); - int ret; if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS) return -EBUSY; @@ -525,47 +543,46 @@ static int opt3001_write_raw(struct iio_dev *iio, if (val != 0) return -EINVAL; - mutex_lock(&opt->lock); - ret = opt3001_set_int_time(opt, val2); - mutex_unlock(&opt->lock); + guard(mutex)(&opt->lock); - return ret; + return opt3001_set_int_time(opt, val2); } static int opt3001_read_event_value(struct iio_dev *iio, - const struct iio_chan_spec *chan, enum iio_event_type type, - enum iio_event_direction dir, enum iio_event_info info, - int *val, int *val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct opt3001 *opt = iio_priv(iio); - int ret = IIO_VAL_INT_PLUS_MICRO; - mutex_lock(&opt->lock); + guard(mutex)(&opt->lock); switch (dir) { case IIO_EV_DIR_RISING: opt3001_to_iio_ret(opt, opt->high_thresh_exp, - opt->high_thresh_mantissa, val, val2); - break; + opt->high_thresh_mantissa, val, val2); + return IIO_VAL_INT_PLUS_MICRO; case IIO_EV_DIR_FALLING: opt3001_to_iio_ret(opt, opt->low_thresh_exp, - opt->low_thresh_mantissa, val, val2); - break; + opt->low_thresh_mantissa, val, val2); + return IIO_VAL_INT_PLUS_MICRO; default: - ret = -EINVAL; + return -EINVAL; } - - mutex_unlock(&opt->lock); - - return ret; } static int opt3001_write_event_value(struct iio_dev *iio, - const struct iio_chan_spec *chan, enum iio_event_type type, - enum iio_event_direction dir, enum iio_event_info info, - int val, int val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct opt3001 *opt = iio_priv(iio); + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; int ret; int whole; int integer; @@ -580,12 +597,12 @@ static int opt3001_write_event_value(struct iio_dev *iio, if (val < 0) return -EINVAL; - mutex_lock(&opt->lock); + guard(mutex)(&opt->lock); ret = opt3001_find_scale(opt, val, val2, &exponent); if (ret < 0) { - dev_err(opt->dev, "can't find scale for %d.%06u\n", val, val2); - goto err; + dev_err(dev, "can't find scale for %d.%06u\n", val, val2); + return ret; } whole = opt->chip_info->factor_whole; @@ -608,25 +625,22 @@ static int opt3001_write_event_value(struct iio_dev *iio, opt->low_thresh_exp = exponent; break; default: - ret = -EINVAL; - goto err; + return -EINVAL; } - ret = i2c_smbus_write_word_swapped(opt->client, reg, value); + ret = i2c_smbus_write_word_swapped(client, reg, value); if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", reg); - goto err; + dev_err(dev, "failed to write register %02x\n", reg); + return ret; } -err: - mutex_unlock(&opt->lock); - - return ret; + return 0; } static int opt3001_read_event_config(struct iio_dev *iio, - const struct iio_chan_spec *chan, enum iio_event_type type, - enum iio_event_direction dir) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) { struct opt3001 *opt = iio_priv(iio); @@ -634,10 +648,14 @@ static int opt3001_read_event_config(struct iio_dev *iio, } static int opt3001_write_event_config(struct iio_dev *iio, - const struct iio_chan_spec *chan, enum iio_event_type type, - enum iio_event_direction dir, bool state) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) { struct opt3001 *opt = iio_priv(iio); + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; int ret; u16 mode; u16 reg; @@ -648,33 +666,29 @@ static int opt3001_write_event_config(struct iio_dev *iio, if (!state && opt->mode == OPT3001_CONFIGURATION_M_SHUTDOWN) return 0; - mutex_lock(&opt->lock); + guard(mutex)(&opt->lock); mode = state ? OPT3001_CONFIGURATION_M_CONTINUOUS : OPT3001_CONFIGURATION_M_SHUTDOWN; - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); - goto err; + dev_err(dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + return ret; } reg = ret; opt3001_set_mode(opt, ®, mode); - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION, - reg); + ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg); if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_CONFIGURATION); - goto err; + dev_err(dev, "failed to write register %02x\n", + OPT3001_CONFIGURATION); + return ret; } -err: - mutex_unlock(&opt->lock); - - return ret; + return 0; } static const struct iio_info opt3001_info = { @@ -689,47 +703,69 @@ static const struct iio_info opt3001_info = { static int opt3001_read_id(struct opt3001 *opt) { + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; char manufacturer[2]; u16 device_id; int ret; - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_MANUFACTURER_ID); - if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_MANUFACTURER_ID); - return ret; - } + ret = i2c_smbus_read_word_swapped(client, OPT3001_MANUFACTURER_ID); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read register %02x\n", + OPT3001_MANUFACTURER_ID); manufacturer[0] = ret >> 8; manufacturer[1] = ret & 0xff; - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID); - if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_DEVICE_ID); - return ret; - } + ret = i2c_smbus_read_word_swapped(client, OPT3001_DEVICE_ID); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read register %02x\n", + OPT3001_DEVICE_ID); device_id = ret; - dev_info(opt->dev, "Found %c%c OPT%04x\n", manufacturer[0], - manufacturer[1], device_id); + dev_info(dev, "Found %c%c OPT%04x\n", manufacturer[0], manufacturer[1], + device_id); return 0; } -static int opt3001_configure(struct opt3001 *opt) +static void opt3001_power_off(void *data) { + struct opt3001 *opt = data; + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; + u16 reg_val; int ret; - u16 reg; - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); - return ret; + dev_err(dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + return; } + reg_val = ret; + opt3001_set_mode(opt, ®_val, OPT3001_CONFIGURATION_M_SHUTDOWN); + + ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg_val); + if (ret < 0) + dev_err(dev, "failed to write to register %02x\n", + OPT3001_CONFIGURATION); +} + +static int opt3001_configure(struct opt3001 *opt) +{ + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; + int ret; + u16 reg; + + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + reg = ret; /* Enable automatic full-scale setting mode */ @@ -751,30 +787,28 @@ static int opt3001_configure(struct opt3001 *opt) reg &= ~OPT3001_CONFIGURATION_ME; reg &= ~OPT3001_CONFIGURATION_FC_MASK; - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION, - reg); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_CONFIGURATION); - return ret; - } + ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to write register %02x\n", + OPT3001_CONFIGURATION); - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_LOW_LIMIT); - if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_LOW_LIMIT); - return ret; - } + ret = devm_add_action_or_reset(dev, opt3001_power_off, opt); + if (ret) + return dev_err_probe(dev, ret, + "failed to register power off function\n"); + + ret = i2c_smbus_read_word_swapped(client, OPT3001_LOW_LIMIT); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read register %02x\n", + OPT3001_LOW_LIMIT); opt->low_thresh_mantissa = OPT3001_REG_MANTISSA(ret); opt->low_thresh_exp = OPT3001_REG_EXPONENT(ret); - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_HIGH_LIMIT); - if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_HIGH_LIMIT); - return ret; - } + ret = i2c_smbus_read_word_swapped(client, OPT3001_HIGH_LIMIT); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read register %02x\n", + OPT3001_HIGH_LIMIT); opt->high_thresh_mantissa = OPT3001_REG_MANTISSA(ret); opt->high_thresh_exp = OPT3001_REG_EXPONENT(ret); @@ -786,6 +820,8 @@ static irqreturn_t opt3001_irq(int irq, void *_iio) { struct iio_dev *iio = _iio; struct opt3001 *opt = iio_priv(iio); + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; int ret; bool wake_result_ready_queue = false; enum iio_chan_type chan_type = opt->chip_info->chan_type; @@ -794,10 +830,10 @@ static irqreturn_t opt3001_irq(int irq, void *_iio) if (!ok_to_ignore_lock) mutex_lock(&opt->lock); - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); + dev_err(dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); goto out; } @@ -805,21 +841,21 @@ static irqreturn_t opt3001_irq(int irq, void *_iio) OPT3001_CONFIGURATION_M_CONTINUOUS) { if (ret & OPT3001_CONFIGURATION_FH) iio_push_event(iio, - IIO_UNMOD_EVENT_CODE(chan_type, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - iio_get_time_ns(iio)); + IIO_UNMOD_EVENT_CODE(chan_type, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + iio_get_time_ns(iio)); if (ret & OPT3001_CONFIGURATION_FL) iio_push_event(iio, - IIO_UNMOD_EVENT_CODE(chan_type, 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - iio_get_time_ns(iio)); + IIO_UNMOD_EVENT_CODE(chan_type, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + iio_get_time_ns(iio)); } else if (ret & OPT3001_CONFIGURATION_CRF) { - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT); + ret = i2c_smbus_read_word_swapped(client, OPT3001_RESULT); if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_RESULT); + dev_err(dev, "failed to read register %02x\n", + OPT3001_RESULT); goto out; } opt->result = ret; @@ -852,12 +888,13 @@ static int opt3001_probe(struct i2c_client *client) opt = iio_priv(iio); opt->client = client; - opt->dev = dev; opt->chip_info = i2c_get_match_data(client); - mutex_init(&opt->lock); + ret = devm_mutex_init(dev, &opt->lock); + if (ret) + return ret; + init_waitqueue_head(&opt->result_ready_queue); - i2c_set_clientdata(client, iio); if (opt->chip_info->has_id) { ret = opt3001_read_id(opt); @@ -875,55 +912,20 @@ static int opt3001_probe(struct i2c_client *client) iio->modes = INDIO_DIRECT_MODE; iio->info = &opt3001_info; - ret = devm_iio_device_register(dev, iio); - if (ret) { - dev_err(dev, "failed to register IIO device\n"); - return ret; - } - /* Make use of INT pin only if valid IRQ no. is given */ if (irq > 0) { - ret = request_threaded_irq(irq, NULL, opt3001_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "opt3001", iio); - if (ret) { - dev_err(dev, "failed to request IRQ #%d\n", irq); + ret = devm_request_threaded_irq(dev, irq, NULL, opt3001_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "opt3001", iio); + if (ret) return ret; - } + opt->use_irq = true; } else { - dev_dbg(opt->dev, "enabling interrupt-less operation\n"); - } - - return 0; -} - -static void opt3001_remove(struct i2c_client *client) -{ - struct iio_dev *iio = i2c_get_clientdata(client); - struct opt3001 *opt = iio_priv(iio); - int ret; - u16 reg; - - if (opt->use_irq) - free_irq(client->irq, iio); - - ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); - if (ret < 0) { - dev_err(opt->dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); - return; + dev_dbg(dev, "enabling interrupt-less operation\n"); } - reg = ret; - opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN); - - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION, - reg); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_CONFIGURATION); - } + return devm_iio_device_register(dev, iio); } static const struct opt3001_chip_info opt3001_chip_information = { @@ -964,7 +966,6 @@ MODULE_DEVICE_TABLE(of, opt3001_of_match); static struct i2c_driver opt3001_driver = { .probe = opt3001_probe, - .remove = opt3001_remove, .id_table = opt3001_id, .driver = { diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c index dd152d921b48..aa3d87995b7c 100644 --- a/drivers/iio/light/opt4001.c +++ b/drivers/iio/light/opt4001.c @@ -39,7 +39,7 @@ #define OPT4001_CTRL_OPER_MODE_MASK GENMASK(5, 4) #define OPT4001_CTRL_LATCH_MASK GENMASK(3, 3) #define OPT4001_CTRL_INT_POL_MASK GENMASK(2, 2) -#define OPT4001_CTRL_FAULT_COUNT GENMASK(0, 1) +#define OPT4001_CTRL_FAULT_COUNT_MASK GENMASK(1, 0) /* OPT4001 constants */ #define OPT4001_DEVICE_ID_VAL 0x121 @@ -173,6 +173,7 @@ static int opt4001_read_lux_value(struct iio_dev *indio_dev, u8 crc; u8 calc_crc; u64 lux_raw; + u32 rem; int ret; ret = regmap_read(chip->regmap, OPT4001_LIGHT1_MSB, &light1); @@ -199,8 +200,8 @@ static int opt4001_read_lux_value(struct iio_dev *indio_dev, lux_raw = lux_raw << exp; lux_raw = lux_raw * chip->chip_info->mul; - *val = div_u64_rem(lux_raw, chip->chip_info->div, val2); - *val2 = *val2 * 100; + *val = div_u64_rem(lux_raw, chip->chip_info->div, &rem); + *val2 = rem * 100; return IIO_VAL_INT_PLUS_NANO; } @@ -222,33 +223,14 @@ static int opt4001_set_conf(struct opt4001_chip *chip) return ret; } -static int opt4001_power_down(struct opt4001_chip *chip) -{ - struct device *dev = &chip->client->dev; - int ret; - unsigned int reg; - - ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, ®); - if (ret) { - dev_err(dev, "Failed to read configuration\n"); - return ret; - } - - /* MODE_OFF is 0x0 so just set bits to 0 */ - reg &= ~OPT4001_CTRL_OPER_MODE_MASK; - - ret = regmap_write(chip->regmap, OPT4001_CTRL, reg); - if (ret) - dev_err(dev, "Failed to set configuration to power down\n"); - - return ret; -} - static void opt4001_chip_off_action(void *data) { struct opt4001_chip *chip = data; + int ret; - opt4001_power_down(chip); + ret = regmap_clear_bits(chip->regmap, OPT4001_CTRL, OPT4001_CTRL_OPER_MODE_MASK); + if (ret) + dev_err(&chip->client->dev, "Failed to power down\n"); } static const struct iio_chan_spec opt4001_channels[] = { @@ -287,6 +269,9 @@ static int opt4001_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_INT_TIME: + if (val) + return -EINVAL; + int_time = opt4001_als_time_to_index(val2); if (int_time < 0) return int_time; diff --git a/drivers/iio/light/opt4060.c b/drivers/iio/light/opt4060.c index c391ad3271c6..8253a6a8bee4 100644 --- a/drivers/iio/light/opt4060.c +++ b/drivers/iio/light/opt4060.c @@ -632,6 +632,9 @@ static int opt4060_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_INT_TIME: + if (val) + return -EINVAL; + int_time = opt4060_als_time_to_index(val2); if (int_time < 0) return int_time; @@ -710,6 +713,7 @@ static ssize_t opt4060_read_ev_period(struct opt4060_chip *chip, int *val, { int ret, pers, fault_count, int_time; u64 uval; + u32 rem; int_time = opt4060_int_time_reg[chip->int_time][0]; @@ -735,7 +739,8 @@ static ssize_t opt4060_read_ev_period(struct opt4060_chip *chip, int *val, } uval = mul_u32_u32(int_time, pers); - *val = div_u64_rem(uval, MICRO, val2); + *val = div_u64_rem(uval, MICRO, &rem); + *val2 = rem; return IIO_VAL_INT_PLUS_MICRO; } @@ -805,7 +810,7 @@ static int opt4060_get_thresholds(struct opt4060_chip *chip, u32 *th_lo, u32 *th ret = regmap_read(chip->regmap, OPT4060_THRESHOLD_HIGH, ®val); if (ret) { - dev_err(chip->dev, "Failed to read THRESHOLD_LOW.\n"); + dev_err(chip->dev, "Failed to read THRESHOLD_HIGH.\n"); return ret; } *th_hi = opt4060_calc_val_from_th_reg(regval); @@ -1200,7 +1205,7 @@ static int opt4060_setup_trigger(struct opt4060_chip *chip, struct iio_dev *idev IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, idev); if (ret) - return dev_err_probe(chip->dev, ret, "Could not request IRQ\n"); + return ret; init_completion(&chip->completion); diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index f961973892f2..7d82efc31f3a 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -987,11 +987,8 @@ static int rpr0521_probe(struct i2c_client *client) rpr0521_drdy_irq_handler, rpr0521_drdy_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "rpr0521_event", indio_dev); - if (ret < 0) { - dev_err(&client->dev, "request irq %d for trigger0 failed\n", - client->irq); + if (ret) goto err_pm_disable; - } ret = devm_iio_trigger_register(indio_dev->dev.parent, data->drdy_trigger0); @@ -1071,7 +1068,10 @@ static int rpr0521_runtime_resume(struct device *dev) struct rpr0521_data *data = iio_priv(indio_dev); int ret; - regcache_sync(data->regmap); + ret = regcache_sync(data->regmap); + if (ret < 0) + return ret; + if (data->als_ps_need_en) { ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); if (ret < 0) diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 4601ae5d2009..bb7c99041819 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -1251,10 +1251,8 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) IRQF_TRIGGER_FALLING | IRQF_NO_THREAD, "si1145_irq", trig); - if (ret < 0) { - dev_err(&client->dev, "irq request failed\n"); + if (ret) return ret; - } ret = devm_iio_trigger_register(&client->dev, trig); if (ret) diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c index bcd729a9924e..94d5261b2663 100644 --- a/drivers/iio/light/st_uvis25_core.c +++ b/drivers/iio/light/st_uvis25_core.c @@ -196,11 +196,8 @@ static int st_uvis25_allocate_trigger(struct iio_dev *iio_dev) st_uvis25_trigger_handler_thread, irq_type | IRQF_ONESHOT, iio_dev->name, hw); - if (err) { - dev_err(dev, "failed to request trigger irq %d\n", - hw->irq); + if (err) return err; - } hw->trig = devm_iio_trigger_alloc(dev, "%s-trigger", iio_dev->name); diff --git a/drivers/iio/light/st_uvis25_spi.c b/drivers/iio/light/st_uvis25_spi.c index c4c15093e9e5..0f78a0abfafb 100644 --- a/drivers/iio/light/st_uvis25_spi.c +++ b/drivers/iio/light/st_uvis25_spi.c @@ -46,7 +46,7 @@ static const struct of_device_id st_uvis25_spi_of_match[] = { MODULE_DEVICE_TABLE(of, st_uvis25_spi_of_match); static const struct spi_device_id st_uvis25_spi_id_table[] = { - { ST_UVIS25_DEV_NAME }, + { .name = ST_UVIS25_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(spi, st_uvis25_spi_id_table); diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index e7ce6f32592b..7c8a1d2b2ed0 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -673,11 +673,8 @@ static int stk3310_probe(struct i2c_client *client) IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "stk3310_event", indio_dev); - if (ret < 0) { - dev_err(&client->dev, "request irq %d failed\n", - client->irq); + if (ret) goto err_standby; - } } ret = iio_device_register(indio_dev); diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index b61442c5c1be..b392943e51c8 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -9,8 +9,6 @@ * TCS34727) * * Datasheet: http://ams.com/eng/content/download/319364/1117183/file/TCS3472_Datasheet_EN_v2.pdf - * - * TODO: wait time */ #include <linux/cleanup.h> @@ -19,6 +17,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/pm.h> +#include <linux/units.h> #include <linux/iio/buffer.h> #include <linux/iio/events.h> @@ -53,19 +52,30 @@ #define TCS3472_STATUS_AINT BIT(4) #define TCS3472_STATUS_AVALID BIT(0) #define TCS3472_ENABLE_AIEN BIT(4) +#define TCS3472_ENABLE_WEN BIT(3) #define TCS3472_ENABLE_AEN BIT(1) #define TCS3472_ENABLE_PON BIT(0) +#define TCS3472_ENABLE_RUN \ + (TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON | TCS3472_ENABLE_WEN) #define TCS3472_CONTROL_AGAIN_MASK (BIT(0) | BIT(1)) +#define TCS3472_CONFIG_WLONG BIT(1) + +#define TCS3472_ATIME_TO_US(atime) (((256) - (atime)) * 2400) struct tcs3472_data { struct i2c_client *client; struct mutex lock; + int target_freq_hz; + int target_freq_uhz; u16 low_thresh; u16 high_thresh; u8 enable; + u8 enable_pre_suspend; u8 control; u8 atime; u8 apers; + u8 wtime; + bool wlong; }; static const struct iio_event_spec tcs3472_events[] = { @@ -91,6 +101,7 @@ static const struct iio_event_spec tcs3472_events[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBSCALE) | \ BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .channel2 = IIO_MOD_LIGHT_##_color, \ .address = _addr, \ .scan_index = _si, \ @@ -114,9 +125,65 @@ static const struct iio_chan_spec tcs3472_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), }; +/* + * The chip's cycle time is the sum of three components: + * - ATIME: the programmable RGBC integration time. + * - The fixed RGBC initialization time (2400 us). + * - WTIME: the wait time, used only if WEN is set. If WLONG is active, + * the wait step is multiplied by 12 (2400 us -> 28800 us). + */ +static unsigned int tcs3472_cycle_time_us(struct tcs3472_data *data) +{ + unsigned int atime_us = TCS3472_ATIME_TO_US(data->atime); + unsigned int init_us = 2400; + unsigned int wtime_us; + + if (!(data->enable & TCS3472_ENABLE_WEN)) + wtime_us = 0; + else if (data->wlong) + wtime_us = (256 - data->wtime) * 28800; + else + wtime_us = (256 - data->wtime) * 2400; + + return atime_us + init_us + wtime_us; +} + +/* + * Convert a cycle time in microseconds to a frequency in Hz and microhertz. + * + * Given cycle_us = T (the cycle period in microseconds), the corresponding + * frequency is: + * f = 1e6 / T [Hz] + * + * The result is split into the IIO_VAL_INT_PLUS_MICRO format: + * val = floor(1e6 / T) [Hz] + * val2 = (1e6 mod T) * 1e6 / T [microhertz] + */ +static void tcs3472_cycle_to_freq(unsigned int cycle_us, int *val, int *val2) +{ + *val = USEC_PER_SEC / cycle_us; + *val2 = div_u64((u64)(USEC_PER_SEC % cycle_us) * USEC_PER_SEC, + cycle_us); +} + static int tcs3472_req_data(struct tcs3472_data *data) { - int tries = 50; + /* + * The worst-case cycle time is reached with ATIME=0x00, WTIME=0x00 + * and WLONG=1. So: + * 614 ms (Max Integration Time) + * + 2.4 ms (RGBC Init) + * + 7.37 s (Max Wait Time) + * = ~ 8 s (Total Max cycle time). + * Use that as a polling upper bound; in normal operation the loop + * exits as soon as AVALID is set. So the total number of tries in 8 + * seconds considering a polling period of 20 ms is 400. + * Considering a 20% margin due to oscillator tolerance, the total + * duration becomes approximately 9.8 seconds, which corresponds to + * about 480 steps. Therefore, setting it to 500 appears to be a + * reasonable and safe trade-off. + */ + int tries = 500; int ret; while (tries--) { @@ -164,18 +231,165 @@ static int tcs3472_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME: *val = 0; - *val2 = (256 - data->atime) * 2400; + *val2 = TCS3472_ATIME_TO_US(data->atime); return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: { + unsigned int cycle_us; + + guard(mutex)(&data->lock); + cycle_us = tcs3472_cycle_time_us(data); + tcs3472_cycle_to_freq(cycle_us, val, val2); + return IIO_VAL_INT_PLUS_MICRO; + } default: return -EINVAL; } } +/* + * __tcs3472_set_sampling_freq() - implementation of sampling frequency + * configuration. The caller must hold data->lock. + */ +static int __tcs3472_set_sampling_freq(struct tcs3472_data *data, + int val, int val2) +{ + unsigned int atime_us; + unsigned int init_us = 2400; + u64 cycle_us; + s64 wait_us; + int wtime; + bool wlong = false; + u8 config; + int ret; + + if (val < 0 || val2 < 0 || (val == 0 && val2 == 0)) + return -EINVAL; + + atime_us = TCS3472_ATIME_TO_US(data->atime); + + /* + * cycle_us = 1 / freq, expressed in microseconds. + * Numerator: 1 [s] = PSEC_PER_SEC [ps] + * Denominator: freq [Hz] * MICROHZ_PER_HZ + val2 [uHz] = freq in [uHz] + * Result: ps / uHz = us + */ + cycle_us = div64_u64(PSEC_PER_SEC, (u64)val * MICROHZ_PER_HZ + val2); + + /* + * wait_us can be negative when the requested frequency is too high + * to be reached, or very large when the requested frequency is + * close to zero. Use s64 to cover the full range: + * + * cycle_us = PSEC_PER_SEC / (val * MICROHZ_PER_HZ + val2) + * + * The divisor of the formula above reaches its maximum when + * val = val2 = INT_MAX: + * INT_MAX * MICROHZ_PER_HZ + INT_MAX = ~2.15e18 + * so cycle_us_min = floor(1e12 / 2.15e18) = 0. + * + * The divisor reaches its minimum (1) when val = 0 and val2 = 1, + * so cycle_us_max = 1e12 / 1 = 1e12. + * + * Therefore: + * wait_us_min = 0 - 2400 - 612000 = -616800 + * wait_us_max = 1e12 - 2400 - 2400 = 999999995200 + * + * Both fit comfortably in s64. + */ + wait_us = (s64)cycle_us - init_us - atime_us; + if (wait_us < 2400) { + if (data->enable & TCS3472_ENABLE_WEN) { + u8 enable = data->enable & ~TCS3472_ENABLE_WEN; + + ret = i2c_smbus_write_byte_data(data->client, + TCS3472_ENABLE, enable); + if (ret) + return ret; + + data->enable = enable; + } + + data->target_freq_hz = val; + data->target_freq_uhz = val2; + return 0; + } + + /* + * Wait state is needed: make sure WEN is active before programming + * WTIME (and possibly WLONG). + */ + if (!(data->enable & TCS3472_ENABLE_WEN)) { + u8 enable = data->enable | TCS3472_ENABLE_WEN; + + ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, + enable); + if (ret) + return ret; + + data->enable = enable; + } + + wtime = 256 - DIV_ROUND_CLOSEST_ULL(wait_us, 2400); + if (wtime < 0) { + /* + * If wait_us is too high (so the requested frequency is too + * low), the resulting wait exceeds what WTIME can represent + * (max 614 ms without WLONG). Enable WLONG, whose step is 12x + * longer (28.8 ms instead of 2.4 ms), and recompute. + */ + wlong = true; + wtime = 256 - DIV_ROUND_CLOSEST_ULL(wait_us, 28800); + } + + if (wlong != data->wlong) { + ret = i2c_smbus_read_byte_data(data->client, TCS3472_CONFIG); + if (ret < 0) + return ret; + + config = ret; + if (wlong) + config |= TCS3472_CONFIG_WLONG; + else + config &= ~TCS3472_CONFIG_WLONG; + + ret = i2c_smbus_write_byte_data(data->client, TCS3472_CONFIG, + config); + if (ret) + return ret; + + data->wlong = wlong; + } + + /* + * If the requested wait is so long that even WLONG cannot + * cover it, wtime may still be negative. Saturate to 0, + * which is the largest possible wait (256 * 28.8 ms = 7.37 s). + */ + wtime = clamp(wtime, 0, 255); + ret = i2c_smbus_write_byte_data(data->client, TCS3472_WTIME, wtime); + if (ret) + return ret; + + data->wtime = wtime; + data->target_freq_hz = val; + data->target_freq_uhz = val2; + + return 0; +} + +static int tcs3472_set_sampling_freq(struct tcs3472_data *data, + int val, int val2) +{ + guard(mutex)(&data->lock); + return __tcs3472_set_sampling_freq(data, val, val2); +} + static int tcs3472_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct tcs3472_data *data = iio_priv(indio_dev); + int ret; int i; switch (mask) { @@ -196,15 +410,31 @@ static int tcs3472_write_raw(struct iio_dev *indio_dev, if (val != 0) return -EINVAL; for (i = 0; i < 256; i++) { - if (val2 == (256 - i) * 2400) { - data->atime = i; - return i2c_smbus_write_byte_data( - data->client, TCS3472_ATIME, - data->atime); - } - + if (val2 != (256 - i) * 2400) + continue; + + guard(mutex)(&data->lock); + + ret = i2c_smbus_write_byte_data(data->client, + TCS3472_ATIME, i); + if (ret) + return ret; + + data->atime = i; + + /* + * ATIME just changed, so the cycle time changed too. + * Re-run the sampling frequency logic to recompute + * WTIME and preserve the user's last requested + * frequency. Lock is already held. + */ + return __tcs3472_set_sampling_freq(data, + data->target_freq_hz, + data->target_freq_uhz); } return -EINVAL; + case IIO_CHAN_INFO_SAMP_FREQ: + return tcs3472_set_sampling_freq(data, val, val2); default: return -EINVAL; } @@ -234,7 +464,7 @@ static int tcs3472_read_event(struct iio_dev *indio_dev, data->high_thresh : data->low_thresh; return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: - period = (256 - data->atime) * 2400 * + period = tcs3472_cycle_time_us(data) * tcs3472_intr_pers[data->apers]; *val = period / USEC_PER_SEC; *val2 = period % USEC_PER_SEC; @@ -279,11 +509,13 @@ static int tcs3472_write_event(struct iio_dev *indio_dev, data->low_thresh = val; return 0; - case IIO_EV_INFO_PERIOD: + case IIO_EV_INFO_PERIOD:{ + unsigned int cycle_us; + period = val * USEC_PER_SEC + val2; + cycle_us = tcs3472_cycle_time_us(data); for (i = 1; i < ARRAY_SIZE(tcs3472_intr_pers) - 1; i++) { - if (period <= (256 - data->atime) * 2400 * - tcs3472_intr_pers[i]) + if (period <= cycle_us * tcs3472_intr_pers[i]) break; } ret = i2c_smbus_write_byte_data(data->client, TCS3472_PERS, i); @@ -293,6 +525,7 @@ static int tcs3472_write_event(struct iio_dev *indio_dev, data->apers = i; return 0; + } default: return -EINVAL; } @@ -434,17 +667,16 @@ static const struct iio_info tcs3472_info = { static int tcs3472_powerdown(struct tcs3472_data *data) { int ret; - u8 enable_mask = TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; guard(mutex)(&data->lock); + data->enable_pre_suspend = data->enable; + ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, - data->enable & ~enable_mask); + data->enable & ~TCS3472_ENABLE_RUN); if (ret) return ret; - data->enable &= ~enable_mask; - return 0; } @@ -458,7 +690,9 @@ static int tcs3472_probe(struct i2c_client *client) struct device *dev = &client->dev; struct tcs3472_data *data; struct iio_dev *indio_dev; + unsigned int cycle_us; int ret; + u8 enable; indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) @@ -498,6 +732,16 @@ static int tcs3472_probe(struct i2c_client *client) return ret; data->atime = ret; + ret = i2c_smbus_read_byte_data(data->client, TCS3472_WTIME); + if (ret < 0) + return ret; + data->wtime = ret; + + ret = i2c_smbus_read_byte_data(data->client, TCS3472_CONFIG); + if (ret < 0) + return ret; + data->wlong = (ret & TCS3472_CONFIG_WLONG) ? 1 : 0; + ret = i2c_smbus_read_word_data(data->client, TCS3472_AILT); if (ret < 0) return ret; @@ -518,14 +762,30 @@ static int tcs3472_probe(struct i2c_client *client) if (ret < 0) return ret; - /* enable device */ - data->enable = ret | TCS3472_ENABLE_PON | TCS3472_ENABLE_AEN; - data->enable &= ~TCS3472_ENABLE_AIEN; - ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, - data->enable); + /* + * Enable the chip in its full running state, including WEN. The + * actual wait time is controlled by the WTIME and WLONG registers, + * which retain their power-on defaults until userspace writes to + * sampling_frequency. + */ + enable = (ret | TCS3472_ENABLE_RUN) & ~TCS3472_ENABLE_AIEN; + + ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, enable); if (ret < 0) return ret; + data->enable = enable; + + /* + * Initialize target frequency from the chip's current state so that + * subsequent integration_time changes via IIO_CHAN_INFO_INT_TIME can + * preserve a meaningful sampling rate, even before userspace writes + * sampling_frequency for the first time. + */ + cycle_us = tcs3472_cycle_time_us(data); + tcs3472_cycle_to_freq(cycle_us, &data->target_freq_hz, + &data->target_freq_uhz); + ret = devm_add_action_or_reset(dev, tcs3472_powerdown_action, data); if (ret) return ret; @@ -561,16 +821,21 @@ static int tcs3472_resume(struct device *dev) struct tcs3472_data *data = iio_priv(i2c_get_clientdata( to_i2c_client(dev))); int ret; - u8 enable_mask = TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; guard(mutex)(&data->lock); + /* + * Restore the full ENABLE register from the snapshot taken in + * tcs3472_powerdown(). This preserves the user's last + * sampling_frequency configuration (in particular the WEN bit) + * across suspend/resume. + */ ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, - data->enable | enable_mask); + data->enable_pre_suspend); if (ret) return ret; - data->enable |= enable_mask; + data->enable = data->enable_pre_suspend; return 0; } diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index 45f3513d931e..7bef0c3118c2 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -754,7 +754,7 @@ static int tsl2563_probe(struct i2c_client *client) "tsl2563_event", indio_dev); if (err) - return dev_err_probe(dev, err, "irq request error\n"); + return err; } err = tsl2563_configure(chip); diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index a0dd122af2cf..53fd423aa7ae 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -456,12 +456,8 @@ static int tsl2583_chip_init_and_power_on(struct iio_dev *indio_dev) usleep_range(3000, 3500); - ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON | - TSL2583_CNTL_ADC_ENBL); - if (ret < 0) - return ret; - - return ret; + return tsl2583_set_power_state(chip, + TSL2583_CNTL_PWR_ON | TSL2583_CNTL_ADC_ENBL); } /* Sysfs Interface Functions */ @@ -475,7 +471,7 @@ static ssize_t in_illuminance_input_target_show(struct device *dev, int ret; mutex_lock(&chip->als_mutex); - ret = sprintf(buf, "%d\n", chip->als_settings.als_cal_target); + ret = sysfs_emit(buf, "%d\n", chip->als_settings.als_cal_target); mutex_unlock(&chip->als_mutex); return ret; @@ -533,10 +529,10 @@ static ssize_t in_illuminance_lux_table_show(struct device *dev, int offset = 0; for (i = 0; i < ARRAY_SIZE(chip->als_settings.als_device_lux); i++) { - offset += sprintf(buf + offset, "%u,%u,%u,", - chip->als_settings.als_device_lux[i].ratio, - chip->als_settings.als_device_lux[i].ch0, - chip->als_settings.als_device_lux[i].ch1); + offset += sysfs_emit_at(buf, offset, "%u,%u,%u,", + chip->als_settings.als_device_lux[i].ratio, + chip->als_settings.als_device_lux[i].ch0, + chip->als_settings.als_device_lux[i].ch1); if (chip->als_settings.als_device_lux[i].ratio == 0) { /* * We just printed the first "0" entry. @@ -547,7 +543,7 @@ static ssize_t in_illuminance_lux_table_show(struct device *dev, } } - offset += sprintf(buf + offset, "\n"); + offset += sysfs_emit_at(buf, offset, "\n"); return offset; } @@ -639,14 +635,6 @@ static const struct iio_chan_spec tsl2583_channels[] = { }, }; -static int tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on) -{ - if (on) - return pm_runtime_resume_and_get(&chip->client->dev); - - return pm_runtime_put_autosuspend(&chip->client->dev); -} - static int tsl2583_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -654,7 +642,7 @@ static int tsl2583_read_raw(struct iio_dev *indio_dev, struct tsl2583_chip *chip = iio_priv(indio_dev); int ret, pm_ret; - ret = tsl2583_set_pm_runtime_busy(chip, true); + ret = pm_runtime_resume_and_get(&chip->client->dev); if (ret < 0) return ret; @@ -722,16 +710,16 @@ read_done: mutex_unlock(&chip->als_mutex); if (ret < 0) { - tsl2583_set_pm_runtime_busy(chip, false); + pm_runtime_put_autosuspend(&chip->client->dev); return ret; } /* * Preserve the ret variable if the call to - * tsl2583_set_pm_runtime_busy() is successful so the reading + * pm_runtime_put_autosuspend() is successful so the reading * (if applicable) is returned to user space. */ - pm_ret = tsl2583_set_pm_runtime_busy(chip, false); + pm_ret = pm_runtime_put_autosuspend(&chip->client->dev); if (pm_ret < 0) return pm_ret; @@ -745,7 +733,7 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev, struct tsl2583_chip *chip = iio_priv(indio_dev); int ret; - ret = tsl2583_set_pm_runtime_busy(chip, true); + ret = pm_runtime_resume_and_get(&chip->client->dev); if (ret < 0) return ret; @@ -786,15 +774,15 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev, mutex_unlock(&chip->als_mutex); if (ret < 0) { - tsl2583_set_pm_runtime_busy(chip, false); + pm_runtime_put_autosuspend(&chip->client->dev); return ret; } - ret = tsl2583_set_pm_runtime_busy(chip, false); + ret = pm_runtime_put_autosuspend(&chip->client->dev); if (ret < 0) return ret; - return ret; + return 0; } static const struct iio_info tsl2583_info = { diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 244f44379c36..4486a1d9d84d 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -1274,7 +1274,7 @@ static int tsl2772_read_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_CALIBSCALE: - if (chan->type == IIO_LIGHT) + if (chan->type == IIO_INTENSITY) *val = tsl2772_als_gain[chip->settings.als_gain]; else *val = tsl2772_prox_gain[chip->settings.prox_gain]; @@ -1849,11 +1849,8 @@ static int tsl2772_probe(struct i2c_client *clientp) IRQF_ONESHOT, "TSL2772_event", indio_dev); - if (ret) { - dev_err(&clientp->dev, - "%s: irq request failed\n", __func__); + if (ret) return ret; - } } else { indio_dev->channels = chip->chip_info->channel_without_events; } diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 128ae3f94074..336468d59ea7 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -537,16 +537,6 @@ static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data) return !!(ret & VCNL4000_SELF_TIMED_EN); } -static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on) -{ - struct device *dev = &data->client->dev; - - if (on) - return pm_runtime_resume_and_get(dev); - - return pm_runtime_put_autosuspend(dev); -} - static int vcnl4040_read_als_it(struct vcnl4000_data *data, int *val, int *val2) { int ret; @@ -850,7 +840,7 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = vcnl4000_set_pm_runtime_state(data, true); + ret = pm_runtime_resume_and_get(&data->client->dev); if (ret < 0) return ret; @@ -869,7 +859,7 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, default: ret = -EINVAL; } - vcnl4000_set_pm_runtime_state(data, false); + pm_runtime_put_autosuspend(&data->client->dev); return ret; case IIO_CHAN_INFO_SCALE: if (chan->type != IIO_LIGHT) @@ -1922,7 +1912,7 @@ static void vcnl4000_cleanup(void *data) static int vcnl4000_probe(struct i2c_client *client) { - const char * const regulator_names[] = { "vdd", "vio", "vled" }; + static const char * const regulator_names[] = { "vdd", "vio", "vled" }; struct device *dev = &client->dev; struct vcnl4000_data *data; struct iio_dev *indio_dev; diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index bf3a49b4351d..ce1bd42b0c7c 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -145,16 +145,6 @@ static const struct iio_trigger_ops vcnl4035_trigger_ops = { .set_trigger_state = vcnl4035_als_drdy_set_state, }; -static int vcnl4035_set_pm_runtime_state(struct vcnl4035_data *data, bool on) -{ - struct device *dev = &data->client->dev; - - if (on) - return pm_runtime_resume_and_get(dev); - - return pm_runtime_put_autosuspend(dev); -} - static int vcnl4035_read_info_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val) { @@ -202,11 +192,11 @@ static int vcnl4035_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = vcnl4035_set_pm_runtime_state(data, true); + ret = pm_runtime_resume_and_get(&data->client->dev); if (ret < 0) return ret; ret = vcnl4035_read_info_raw(indio_dev, chan, val); - vcnl4035_set_pm_runtime_state(data, false); + pm_runtime_put_autosuspend(&data->client->dev); return ret; case IIO_CHAN_INFO_INT_TIME: *val = 50; @@ -237,7 +227,7 @@ static int vcnl4035_write_raw(struct iio_dev *indio_dev, if (val <= 0 || val > 800) return -EINVAL; - ret = vcnl4035_set_pm_runtime_state(data, true); + ret = pm_runtime_resume_and_get(&data->client->dev); if (ret < 0) return ret; @@ -247,7 +237,7 @@ static int vcnl4035_write_raw(struct iio_dev *indio_dev, if (!ret) data->als_it_val = val / 100; - vcnl4035_set_pm_runtime_state(data, false); + pm_runtime_put_autosuspend(&data->client->dev); return ret; default: return -EINVAL; @@ -647,7 +637,10 @@ static int vcnl4035_runtime_resume(struct device *dev) struct vcnl4035_data *data = iio_priv(indio_dev); int ret; - regcache_sync(data->regmap); + ret = regcache_sync(data->regmap); + if (ret < 0) + return ret; + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE); if (ret < 0) return ret; diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index 7c837d60dad8..ec9c127e7d8a 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -921,9 +921,7 @@ static int veml6030_set_info(struct iio_dev *indio_dev) IRQF_TRIGGER_LOW | IRQF_ONESHOT, indio_dev->name, indio_dev); if (ret < 0) - return dev_err_probe(&client->dev, ret, - "irq %d request failed\n", - client->irq); + return ret; indio_dev->info = &veml6030_info; } else { diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c index 4f270f405b21..aef8a5333442 100644 --- a/drivers/iio/light/vl6180.c +++ b/drivers/iio/light/vl6180.c @@ -721,7 +721,7 @@ static int vl6180_probe(struct i2c_client *client) IRQF_ONESHOT, indio_dev->name, indio_dev); if (ret) - return dev_err_probe(&client->dev, ret, "devm_request_irq error\n"); + return ret; init_completion(&data->completion); |
