| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * AD7150 capacitive sensor driver supporting AD7150/1/6 |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright 2010-2011 Analog Devices Inc. |
|---|
| 5 | | - * |
|---|
| 6 | | - * Licensed under the GPL-2 or later. |
|---|
| 7 | 6 | */ |
|---|
| 8 | 7 | |
|---|
| 9 | 8 | #include <linux/bitfield.h> |
|---|
| .. | .. |
|---|
| 46 | 45 | #define AD7150_SN1 21 |
|---|
| 47 | 46 | #define AD7150_SN0 22 |
|---|
| 48 | 47 | #define AD7150_ID 23 |
|---|
| 48 | + |
|---|
| 49 | +/* AD7150 masks */ |
|---|
| 50 | +#define AD7150_THRESHTYPE_MSK GENMASK(6, 5) |
|---|
| 49 | 51 | |
|---|
| 50 | 52 | /** |
|---|
| 51 | 53 | * struct ad7150_chip_info - instance specific chip data |
|---|
| .. | .. |
|---|
| 103 | 105 | { |
|---|
| 104 | 106 | int ret; |
|---|
| 105 | 107 | struct ad7150_chip_info *chip = iio_priv(indio_dev); |
|---|
| 108 | + int channel = chan->channel; |
|---|
| 106 | 109 | |
|---|
| 107 | 110 | switch (mask) { |
|---|
| 108 | 111 | case IIO_CHAN_INFO_RAW: |
|---|
| 109 | 112 | ret = i2c_smbus_read_word_data(chip->client, |
|---|
| 110 | | - ad7150_addresses[chan->channel][0]); |
|---|
| 113 | + ad7150_addresses[channel][0]); |
|---|
| 111 | 114 | if (ret < 0) |
|---|
| 112 | 115 | return ret; |
|---|
| 113 | 116 | *val = swab16(ret); |
|---|
| 114 | 117 | return IIO_VAL_INT; |
|---|
| 115 | 118 | case IIO_CHAN_INFO_AVERAGE_RAW: |
|---|
| 116 | 119 | ret = i2c_smbus_read_word_data(chip->client, |
|---|
| 117 | | - ad7150_addresses[chan->channel][1]); |
|---|
| 120 | + ad7150_addresses[channel][1]); |
|---|
| 118 | 121 | if (ret < 0) |
|---|
| 119 | 122 | return ret; |
|---|
| 120 | 123 | *val = swab16(ret); |
|---|
| .. | .. |
|---|
| 138 | 141 | if (ret < 0) |
|---|
| 139 | 142 | return ret; |
|---|
| 140 | 143 | |
|---|
| 141 | | - threshtype = (ret >> 5) & 0x03; |
|---|
| 144 | + threshtype = FIELD_GET(AD7150_THRESHTYPE_MSK, ret); |
|---|
| 142 | 145 | |
|---|
| 143 | 146 | /*check if threshold mode is fixed or adaptive*/ |
|---|
| 144 | 147 | thrfixed = FIELD_GET(AD7150_CFG_FIX, ret); |
|---|
| .. | .. |
|---|
| 162 | 165 | return -EINVAL; |
|---|
| 163 | 166 | } |
|---|
| 164 | 167 | |
|---|
| 165 | | -/* lock should be held */ |
|---|
| 168 | +/* state_lock should be held to ensure consistent state*/ |
|---|
| 169 | + |
|---|
| 166 | 170 | static int ad7150_write_event_params(struct iio_dev *indio_dev, |
|---|
| 167 | 171 | unsigned int chan, |
|---|
| 168 | 172 | enum iio_event_type type, |
|---|
| .. | .. |
|---|
| 185 | 189 | case IIO_EV_TYPE_THRESH: |
|---|
| 186 | 190 | value = chip->threshold[rising][chan]; |
|---|
| 187 | 191 | return i2c_smbus_write_word_data(chip->client, |
|---|
| 188 | | - ad7150_addresses[chan][3], |
|---|
| 189 | | - swab16(value)); |
|---|
| 192 | + ad7150_addresses[chan][3], |
|---|
| 193 | + swab16(value)); |
|---|
| 190 | 194 | case IIO_EV_TYPE_MAG_ADAPTIVE: |
|---|
| 191 | 195 | sens = chip->mag_sensitivity[rising][chan]; |
|---|
| 192 | 196 | timeout = chip->mag_timeout[rising][chan]; |
|---|
| .. | .. |
|---|
| 201 | 205 | ret = i2c_smbus_write_byte_data(chip->client, |
|---|
| 202 | 206 | ad7150_addresses[chan][4], |
|---|
| 203 | 207 | sens); |
|---|
| 204 | | - if (ret < 0) |
|---|
| 208 | + if (ret) |
|---|
| 205 | 209 | return ret; |
|---|
| 206 | | - |
|---|
| 207 | | - ret = i2c_smbus_write_byte_data(chip->client, |
|---|
| 210 | + return i2c_smbus_write_byte_data(chip->client, |
|---|
| 208 | 211 | ad7150_addresses[chan][5], |
|---|
| 209 | 212 | timeout); |
|---|
| 210 | | - if (ret < 0) |
|---|
| 211 | | - return ret; |
|---|
| 212 | | - |
|---|
| 213 | | - return 0; |
|---|
| 214 | 213 | } |
|---|
| 215 | 214 | |
|---|
| 216 | 215 | static int ad7150_write_event_config(struct iio_dev *indio_dev, |
|---|
| .. | .. |
|---|
| 353 | 352 | |
|---|
| 354 | 353 | /* use the event code for consistency reasons */ |
|---|
| 355 | 354 | int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address); |
|---|
| 356 | | - int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) |
|---|
| 357 | | - == IIO_EV_DIR_RISING); |
|---|
| 355 | + int rising = (IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) |
|---|
| 356 | + == IIO_EV_DIR_RISING) ? 1 : 0; |
|---|
| 358 | 357 | |
|---|
| 359 | 358 | switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) { |
|---|
| 360 | 359 | case IIO_EV_TYPE_MAG_ADAPTIVE: |
|---|
| .. | .. |
|---|
| 468 | 467 | }, |
|---|
| 469 | 468 | }; |
|---|
| 470 | 469 | |
|---|
| 471 | | -static const struct iio_chan_spec ad7150_channels[] = { |
|---|
| 472 | | - { |
|---|
| 473 | | - .type = IIO_CAPACITANCE, |
|---|
| 474 | | - .indexed = 1, |
|---|
| 475 | | - .channel = 0, |
|---|
| 476 | | - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
|---|
| 477 | | - BIT(IIO_CHAN_INFO_AVERAGE_RAW), |
|---|
| 478 | | - .event_spec = ad7150_events, |
|---|
| 479 | | - .num_event_specs = ARRAY_SIZE(ad7150_events), |
|---|
| 480 | | - }, { |
|---|
| 481 | | - .type = IIO_CAPACITANCE, |
|---|
| 482 | | - .indexed = 1, |
|---|
| 483 | | - .channel = 1, |
|---|
| 484 | | - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
|---|
| 485 | | - BIT(IIO_CHAN_INFO_AVERAGE_RAW), |
|---|
| 486 | | - .event_spec = ad7150_events, |
|---|
| 487 | | - .num_event_specs = ARRAY_SIZE(ad7150_events), |
|---|
| 488 | | - }, |
|---|
| 489 | | -}; |
|---|
| 470 | +#define AD7150_CAPACITANCE_CHAN(_chan) { \ |
|---|
| 471 | + .type = IIO_CAPACITANCE, \ |
|---|
| 472 | + .indexed = 1, \ |
|---|
| 473 | + .channel = _chan, \ |
|---|
| 474 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
|---|
| 475 | + BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ |
|---|
| 476 | + .event_spec = ad7150_events, \ |
|---|
| 477 | + .num_event_specs = ARRAY_SIZE(ad7150_events), \ |
|---|
| 478 | + } |
|---|
| 490 | 479 | |
|---|
| 491 | | -/* |
|---|
| 492 | | - * threshold events |
|---|
| 493 | | - */ |
|---|
| 480 | +static const struct iio_chan_spec ad7150_channels[] = { |
|---|
| 481 | + AD7150_CAPACITANCE_CHAN(0), |
|---|
| 482 | + AD7150_CAPACITANCE_CHAN(1) |
|---|
| 483 | +}; |
|---|
| 494 | 484 | |
|---|
| 495 | 485 | static irqreturn_t ad7150_event_handler(int irq, void *private) |
|---|
| 496 | 486 | { |
|---|
| .. | .. |
|---|
| 580 | 570 | .write_event_value = &ad7150_write_event_value, |
|---|
| 581 | 571 | }; |
|---|
| 582 | 572 | |
|---|
| 583 | | -/* |
|---|
| 584 | | - * device probe and remove |
|---|
| 585 | | - */ |
|---|
| 586 | | - |
|---|
| 587 | 573 | static int ad7150_probe(struct i2c_client *client, |
|---|
| 588 | 574 | const struct i2c_device_id *id) |
|---|
| 589 | 575 | { |
|---|
| .. | .. |
|---|
| 604 | 590 | indio_dev->name = id->name; |
|---|
| 605 | 591 | indio_dev->channels = ad7150_channels; |
|---|
| 606 | 592 | indio_dev->num_channels = ARRAY_SIZE(ad7150_channels); |
|---|
| 607 | | - /* Establish that the iio_dev is a child of the i2c device */ |
|---|
| 608 | | - indio_dev->dev.parent = &client->dev; |
|---|
| 609 | 593 | |
|---|
| 610 | 594 | indio_dev->info = &ad7150_info; |
|---|
| 611 | 595 | |
|---|