diff options
Diffstat (limited to 'drivers/iio/common')
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 2 | ||||
-rw-r--r-- | drivers/iio/common/ms_sensors/ms_sensors_i2c.c | 2 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_buffer.c | 97 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_core.c | 20 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_trigger.c | 13 |
5 files changed, 67 insertions, 67 deletions
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 595511022795..5b41f9d0d4f3 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -115,7 +115,7 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) return ret; } - return 0; + return 0; #else atomic_set(&st->user_requested_state, state); return _hid_sensor_power_state(st, state); diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c index 669dc7c270f5..ecf7721ecaf4 100644 --- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c +++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c @@ -106,7 +106,7 @@ int ms_sensors_convert_and_read(void *cli, u8 conv, u8 rd, unsigned int delay, u32 *adc) { int ret; - __be32 buf = 0; + __be32 buf = 0; struct i2c_client *client = (struct i2c_client *)cli; /* Trigger conversion */ diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index e18bc6782256..c55898543a47 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -24,81 +24,30 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { - u8 *addr; - int i, n = 0, len; + int i, len; + int total = 0; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned int num_data_channels = sdata->num_data_channels; - unsigned int byte_for_channel = - indio_dev->channels[0].scan_type.storagebits >> 3; - - addr = kmalloc(num_data_channels, GFP_KERNEL); - if (!addr) { - len = -ENOMEM; - goto st_sensors_get_buffer_element_error; - } for (i = 0; i < num_data_channels; i++) { + unsigned int bytes_to_read; + if (test_bit(i, indio_dev->active_scan_mask)) { - addr[n] = indio_dev->channels[i].address; - n++; - } - } - switch (n) { - case 1: - len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - addr[0], byte_for_channel, buf, sdata->multiread_bit); - break; - case 2: - if ((addr[1] - addr[0]) == byte_for_channel) { + bytes_to_read = indio_dev->channels[i].scan_type.storagebits >> 3; len = sdata->tf->read_multiple_byte(&sdata->tb, - sdata->dev, addr[0], byte_for_channel * n, - buf, sdata->multiread_bit); - } else { - u8 *rx_array; - rx_array = kmalloc(byte_for_channel * num_data_channels, - GFP_KERNEL); - if (!rx_array) { - len = -ENOMEM; - goto st_sensors_free_memory; - } + sdata->dev, indio_dev->channels[i].address, + bytes_to_read, + buf + total, sdata->multiread_bit); - len = sdata->tf->read_multiple_byte(&sdata->tb, - sdata->dev, addr[0], - byte_for_channel * num_data_channels, - rx_array, sdata->multiread_bit); - if (len < 0) { - kfree(rx_array); - goto st_sensors_free_memory; - } - - for (i = 0; i < n * byte_for_channel; i++) { - if (i < n) - buf[i] = rx_array[i]; - else - buf[i] = rx_array[n + i]; - } - kfree(rx_array); - len = byte_for_channel * n; + if (len < bytes_to_read) + return -EIO; + + /* Advance the buffer pointer */ + total += len; } - break; - case 3: - len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - addr[0], byte_for_channel * num_data_channels, - buf, sdata->multiread_bit); - break; - default: - len = -EINVAL; - goto st_sensors_free_memory; - } - if (len != byte_for_channel * n) { - len = -EIO; - goto st_sensors_free_memory; } -st_sensors_free_memory: - kfree(addr); -st_sensors_get_buffer_element_error: - return len; + return total; } EXPORT_SYMBOL(st_sensors_get_buffer_element); @@ -109,6 +58,24 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct st_sensor_data *sdata = iio_priv(indio_dev); + /* If we have a status register, check if this IRQ came from us */ + if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) { + u8 status; + + len = sdata->tf->read_byte(&sdata->tb, sdata->dev, + sdata->sensor_settings->drdy_irq.addr_stat_drdy, + &status); + if (len < 0) + dev_err(sdata->dev, "could not read channel status\n"); + + /* + * If this was not caused by any channels on this sensor, + * return IRQ_NONE + */ + if (!(status & (u8)indio_dev->active_scan_mask[0])) + return IRQ_NONE; + } + len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data); if (len < 0) goto st_sensors_get_buffer_element_error; diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index f5a2d445d0c0..dffe00692169 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -301,6 +301,14 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, return -EINVAL; } + if (pdata->open_drain) { + if (!sdata->sensor_settings->drdy_irq.addr_od) + dev_err(&indio_dev->dev, + "open drain requested but unsupported.\n"); + else + sdata->int_pin_open_drain = true; + } + return 0; } @@ -321,6 +329,8 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, else pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; + pdata->open_drain = of_property_read_bool(np, "drive-open-drain"); + return pdata; } #else @@ -374,6 +384,16 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, return err; } + if (sdata->int_pin_open_drain) { + dev_info(&indio_dev->dev, + "set interrupt line to open drain mode\n"); + err = st_sensors_write_data_with_mask(indio_dev, + sdata->sensor_settings->drdy_irq.addr_od, + sdata->sensor_settings->drdy_irq.mask_od, 1); + if (err < 0) + return err; + } + err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); return err; diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 6a8c98327945..da72279fcf99 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -64,6 +64,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, "rising edge\n", irq_trig); irq_trig = IRQF_TRIGGER_RISING; } + + /* + * If the interrupt pin is Open Drain, by definition this + * means that the interrupt line may be shared with other + * peripherals. But to do this we also need to have a status + * register and mask to figure out if this sensor was firing + * the IRQ or not, so we can tell the interrupt handle that + * it was "our" interrupt. + */ + if (sdata->int_pin_open_drain && + sdata->sensor_settings->drdy_irq.addr_stat_drdy) + irq_trig |= IRQF_SHARED; + err = request_threaded_irq(irq, iio_trigger_generic_data_rdy_poll, NULL, |