Lines Matching +full:data +full:- +full:out

1 // SPDX-License-Identifier: GPL-2.0-only
3 * vl6180.c - Support for STMicroelectronics VL6180 ALS, range and proximity
6 * Copyright 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
9 * IIO driver for VL6180 (7-bit I2C slave address 0x29)
86 #define VL6180_STARTSTOP BIT(0) /* start measurement, auto-reset */
141 * struct vl6180_chan_regs - Registers for accessing channels
142 * @drdy_mask: Data ready bit in status register
175 * struct vl6180_custom_data - Data for custom initialization
222 { .addr = client->addr, .len = sizeof(cmdbuf), .buf = (u8 *) &cmdbuf }, in vl6180_read()
223 { .addr = client->addr, .len = len, .buf = databuf, in vl6180_read()
227 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in vl6180_read()
229 dev_err(&client->dev, "failed reading register 0x%04x\n", cmd); in vl6180_read()
236 u8 data; in vl6180_read_byte() local
239 ret = vl6180_read(client, cmd, &data, sizeof(data)); in vl6180_read_byte()
243 return data; in vl6180_read_byte()
248 __be16 data; in vl6180_read_word() local
251 ret = vl6180_read(client, cmd, &data, sizeof(data)); in vl6180_read_word()
255 return be16_to_cpu(data); in vl6180_read_word()
262 { .addr = client->addr, .len = sizeof(buf), .buf = (u8 *) &buf } }; in vl6180_write_byte()
269 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in vl6180_write_byte()
271 dev_err(&client->dev, "failed writing register 0x%04x\n", cmd); in vl6180_write_byte()
282 { .addr = client->addr, .len = sizeof(buf), .buf = (u8 *) &buf } }; in vl6180_write_word()
288 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in vl6180_write_word()
290 dev_err(&client->dev, "failed writing register 0x%04x\n", cmd); in vl6180_write_word()
297 static int vl6180_measure(struct vl6180_data *data, int addr) in vl6180_measure() argument
299 struct i2c_client *client = data->client; in vl6180_measure()
303 mutex_lock(&data->lock); in vl6180_measure()
310 while (tries--) { in vl6180_measure()
321 ret = -EIO; in vl6180_measure()
333 /* Clear the interrupt flag after data read */ in vl6180_measure()
342 mutex_unlock(&data->lock); in vl6180_measure()
404 struct vl6180_data *data = iio_priv(indio_dev); in vl6180_read_raw() local
409 ret = vl6180_measure(data, chan->address); in vl6180_read_raw()
416 *val = data->als_it_ms; in vl6180_read_raw()
422 switch (chan->type) { in vl6180_read_raw()
426 *val2 = data->als_gain_milli * data->als_it_ms; in vl6180_read_raw()
435 return -EINVAL; in vl6180_read_raw()
440 *val = data->als_gain_milli; in vl6180_read_raw()
446 return -EINVAL; in vl6180_read_raw()
462 static int vl6180_hold(struct vl6180_data *data, bool hold) in vl6180_hold() argument
464 return vl6180_write_byte(data->client, VL6180_HOLD, in vl6180_hold()
468 static int vl6180_set_als_gain(struct vl6180_data *data, int val, int val2) in vl6180_set_als_gain() argument
473 return -EINVAL; in vl6180_set_als_gain()
477 return -EINVAL; in vl6180_set_als_gain()
482 mutex_lock(&data->lock); in vl6180_set_als_gain()
483 ret = vl6180_hold(data, true); in vl6180_set_als_gain()
487 ret = vl6180_write_byte(data->client, VL6180_ALS_GAIN, in vl6180_set_als_gain()
491 data->als_gain_milli = vl6180_als_gain_tab[i]; in vl6180_set_als_gain()
494 vl6180_hold(data, false); in vl6180_set_als_gain()
495 mutex_unlock(&data->lock); in vl6180_set_als_gain()
499 static int vl6180_set_it(struct vl6180_data *data, int val, int val2) in vl6180_set_it() argument
505 return -EINVAL; in vl6180_set_it()
507 mutex_lock(&data->lock); in vl6180_set_it()
508 ret = vl6180_hold(data, true); in vl6180_set_it()
512 ret = vl6180_write_word(data->client, VL6180_ALS_IT, it_ms - 1); in vl6180_set_it()
515 data->als_it_ms = it_ms; in vl6180_set_it()
518 vl6180_hold(data, false); in vl6180_set_it()
519 mutex_unlock(&data->lock); in vl6180_set_it()
528 struct vl6180_data *data = iio_priv(indio_dev); in vl6180_write_raw() local
532 return vl6180_set_it(data, val, val2); in vl6180_write_raw()
535 if (chan->type != IIO_LIGHT) in vl6180_write_raw()
536 return -EINVAL; in vl6180_write_raw()
538 return vl6180_set_als_gain(data, val, val2); in vl6180_write_raw()
540 return -EINVAL; in vl6180_write_raw()
550 static int vl6180_power_enable(struct vl6180_data *data) in vl6180_power_enable() argument
553 if (!IS_ERR_OR_NULL(data->avdd)) in vl6180_power_enable()
554 gpiod_set_value_cansleep(data->avdd, 1); in vl6180_power_enable()
556 /* Power-up default is chip enable (CE). */ in vl6180_power_enable()
557 if (!IS_ERR_OR_NULL(data->chip_enable)) { in vl6180_power_enable()
558 gpiod_set_value_cansleep(data->chip_enable, 0); in vl6180_power_enable()
560 gpiod_set_value_cansleep(data->chip_enable, 1); in vl6180_power_enable()
566 static int vl6180_custom_init(struct vl6180_data *data) in vl6180_custom_init() argument
568 struct i2c_client *client = data->client; in vl6180_custom_init()
585 static int vl6180_range_init(struct vl6180_data *data) in vl6180_range_init() argument
587 struct i2c_client *client = data->client; in vl6180_range_init()
598 goto out; in vl6180_range_init()
606 goto out; in vl6180_range_init()
613 goto out; in vl6180_range_init()
618 goto out; in vl6180_range_init()
624 goto out; in vl6180_range_init()
626 /* Set default ranging inter-measurement period to 100ms */ in vl6180_range_init()
629 goto out; in vl6180_range_init()
637 goto out; in vl6180_range_init()
641 goto out; in vl6180_range_init()
645 goto out; in vl6180_range_init()
649 goto out; in vl6180_range_init()
653 goto out; in vl6180_range_init()
657 goto out; in vl6180_range_init()
661 goto out; in vl6180_range_init()
665 goto out; in vl6180_range_init()
669 goto out; in vl6180_range_init()
673 goto out; in vl6180_range_init()
679 goto out; in vl6180_range_init()
683 goto out; in vl6180_range_init()
687 goto out; in vl6180_range_init()
691 goto out; in vl6180_range_init()
695 goto out; in vl6180_range_init()
699 goto out; in vl6180_range_init()
703 goto out; in vl6180_range_init()
707 goto out; in vl6180_range_init()
713 goto out; in vl6180_range_init()
717 goto out; in vl6180_range_init()
724 goto out; in vl6180_range_init()
730 goto out; in vl6180_range_init()
734 out: in vl6180_range_init()
738 static int vl6180_init(struct vl6180_data *data) in vl6180_init() argument
740 struct i2c_client *client = data->client; in vl6180_init()
743 ret = vl6180_power_enable(data); in vl6180_init()
745 dev_err(&client->dev, "failed to configure power\n"); in vl6180_init()
761 dev_err(&client->dev, "invalid model ID %02x\n", ret); in vl6180_init()
762 return -ENODEV; in vl6180_init()
765 ret = vl6180_hold(data, true); in vl6180_init()
775 * system comes out of reset. in vl6180_init()
778 dev_info(&client->dev, "device is not fresh out of reset\n"); in vl6180_init()
781 data->als_it_ms = 100; in vl6180_init()
787 data->als_gain_milli = 1000; in vl6180_init()
792 ret = vl6180_custom_init(data); in vl6180_init()
796 ret = vl6180_range_init(data); in vl6180_init()
809 return vl6180_hold(data, false); in vl6180_init()
814 struct vl6180_data *data = priv; in vl6180_irq_thread() local
815 struct i2c_client *client = data->client; in vl6180_irq_thread()
822 goto out; in vl6180_irq_thread()
837 goto out; in vl6180_irq_thread()
838 data->scan.channels[VL6180_ALS] = ret; in vl6180_irq_thread()
842 goto out; in vl6180_irq_thread()
843 data->scan.channels[VL6180_RANGE] = ret; in vl6180_irq_thread()
847 goto out; in vl6180_irq_thread()
848 data->scan.channels[VL6180_PROX] = ret; in vl6180_irq_thread()
850 iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, in vl6180_irq_thread()
853 out: in vl6180_irq_thread()
859 struct vl6180_data *data = iio_priv(indio_dev); in vl6180_buffer_preenable() local
863 ret = vl6180_read_byte(data->client, VL6180_INTR_CONFIG); in vl6180_buffer_preenable()
869 ret = vl6180_write_byte(data->client, VL6180_INTR_CONFIG, val); in vl6180_buffer_preenable()
876 struct vl6180_data *data = iio_priv(indio_dev); in vl6180_buffer_postdisable() local
880 ret = vl6180_read_byte(data->client, VL6180_INTR_CONFIG); in vl6180_buffer_postdisable()
886 ret = vl6180_write_byte(data->client, VL6180_INTR_CONFIG, val); in vl6180_buffer_postdisable()
899 struct vl6180_data *data; in vl6180_probe() local
905 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); in vl6180_probe()
907 return -ENOMEM; in vl6180_probe()
909 data = iio_priv(indio_dev); in vl6180_probe()
911 data->client = client; in vl6180_probe()
912 mutex_init(&data->lock); in vl6180_probe()
914 indio_dev->info = &vl6180_info; in vl6180_probe()
915 indio_dev->channels = vl6180_channels; in vl6180_probe()
916 indio_dev->num_channels = ARRAY_SIZE(vl6180_channels); in vl6180_probe()
917 indio_dev->name = VL6180_DRV_NAME; in vl6180_probe()
918 indio_dev->modes = INDIO_DIRECT_MODE; in vl6180_probe()
922 * configuration should match the power-up timing. in vl6180_probe()
924 data->avdd = devm_gpiod_get_optional(&client->dev, "avdd", in vl6180_probe()
926 data->chip_enable = devm_gpiod_get_optional(&client->dev, "chip-enable", in vl6180_probe()
929 ret = vl6180_init(data); in vl6180_probe()
933 if (client->irq) { in vl6180_probe()
934 buffer = devm_iio_kfifo_allocate(&client->dev); in vl6180_probe()
936 return -ENOMEM; in vl6180_probe()
939 indio_dev->modes |= INDIO_BUFFER_SOFTWARE; in vl6180_probe()
940 indio_dev->setup_ops = &vl6180_buffer_setup_ops; in vl6180_probe()
942 type = irqd_get_trigger_type(irq_get_irq_data(client->irq)); in vl6180_probe()
943 ret = devm_request_threaded_irq(&client->dev, client->irq, in vl6180_probe()
946 data); in vl6180_probe()
948 dev_err(&client->dev, in vl6180_probe()
954 return devm_iio_device_register(&client->dev, indio_dev); in vl6180_probe()
980 MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>");