This commit is contained in:
Mark Brown
2026-07-31 13:59:01 +01:00
17 changed files with 157 additions and 83 deletions
+19 -11
View File
@@ -609,7 +609,7 @@ static int hid_sensor_custom_add_attributes(struct hid_sensor_custom
&sensor_inst->fields[i].
hid_custom_attribute_group);
if (ret)
break;
goto err_remove_groups;
/* For power or report field store indexes */
if (sensor_inst->fields[i].attribute.attrib_id ==
@@ -621,6 +621,13 @@ static int hid_sensor_custom_add_attributes(struct hid_sensor_custom
}
return ret;
err_remove_groups:
while (--i >= 0)
sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
&sensor_inst->fields[i].hid_custom_attribute_group);
kfree(sensor_inst->fields);
return ret;
}
static void hid_sensor_custom_remove_attributes(struct hid_sensor_custom *
@@ -1005,26 +1012,26 @@ static int hid_sensor_custom_probe(struct platform_device *pdev)
return ret;
}
ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
&enable_sensor_attr_group);
ret = hid_sensor_custom_add_attributes(sensor_inst);
if (ret)
goto err_remove_callback;
ret = hid_sensor_custom_add_attributes(sensor_inst);
if (ret)
goto err_remove_group;
ret = hid_sensor_custom_dev_if_add(sensor_inst);
ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
&enable_sensor_attr_group);
if (ret)
goto err_remove_attributes;
ret = hid_sensor_custom_dev_if_add(sensor_inst);
if (ret)
goto err_remove_group;
return 0;
err_remove_attributes:
hid_sensor_custom_remove_attributes(sensor_inst);
err_remove_group:
sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
&enable_sensor_attr_group);
err_remove_attributes:
hid_sensor_custom_remove_attributes(sensor_inst);
err_remove_callback:
sensor_hub_remove_callback(hsdev, hsdev->usage);
@@ -1042,9 +1049,10 @@ static void hid_sensor_custom_remove(struct platform_device *pdev)
}
hid_sensor_custom_dev_if_remove(sensor_inst);
hid_sensor_custom_remove_attributes(sensor_inst);
/* Remove enable_sensor first as it uses fields via power_state/report_state. */
sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
&enable_sensor_attr_group);
hid_sensor_custom_remove_attributes(sensor_inst);
sensor_hub_remove_callback(hsdev, hsdev->usage);
}
+2
View File
@@ -1076,6 +1076,7 @@ config MAX1363
config MAX14001
tristate "Analog Devices MAX14001/MAX14002 ADC driver"
depends on SPI
select REGMAP
help
Say yes here to build support for Analog Devices MAX14001/MAX14002
Configurable, Isolated 10-bit ADCs for Multi-Range Binary Inputs.
@@ -1086,6 +1087,7 @@ config MAX14001
config MAX34408
tristate "Maxim max34408/max344089 ADC driver"
depends on I2C
select REGMAP_I2C
help
Say yes here to build support for Maxim max34408/max34409 current sense
monitor with 8-bits ADC interface with overcurrent delay/threshold and
+5
View File
@@ -697,6 +697,11 @@ static int ad4080_setup_channel(struct ad4080_state *st, unsigned int ch)
if (ret)
return ret;
ret = iio_backend_data_size_set(st->back[ch],
st->info->channels[0].scan_type.realbits);
if (ret)
return ret;
if (!st->lvds_cnv_en)
return 0;
+30
View File
@@ -53,6 +53,10 @@
#define AXI_AD485X_PACKET_FORMAT_24BIT 0x1
#define AXI_AD485X_PACKET_FORMAT_32BIT 0x2
#define AXI_AD408X_CNTRL_3_FILTER_EN_MSK BIT(0)
#define AXI_AD408X_CNTRL_3_PACKET_FORMAT_MSK GENMASK(3, 2)
#define AXI_AD408X_PACKET_FORMAT_20BIT 0x0
#define AXI_AD408X_PACKET_FORMAT_16BIT 0x1
#define AXI_AD408X_PACKET_FORMAT_14BIT 0x2
#define ADI_AXI_ADC_REG_SYNC_STATUS 0x0068
#define ADI_AXI_ADC_SYNC_STATUS_ADC_SYNC_MSK BIT(0)
@@ -436,6 +440,31 @@ static int axi_adc_ad408x_filter_type_set(struct iio_backend *back,
AXI_AD408X_CNTRL_3_FILTER_EN_MSK);
}
static int axi_adc_ad408x_data_size_set(struct iio_backend *back,
unsigned int size)
{
struct adi_axi_adc_state *st = iio_backend_get_priv(back);
unsigned int val;
switch (size) {
case 20:
val = AXI_AD408X_PACKET_FORMAT_20BIT;
break;
case 16:
val = AXI_AD408X_PACKET_FORMAT_16BIT;
break;
case 14:
val = AXI_AD408X_PACKET_FORMAT_14BIT;
break;
default:
return -EINVAL;
}
return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CNTRL_3,
AXI_AD408X_CNTRL_3_PACKET_FORMAT_MSK,
FIELD_PREP(AXI_AD408X_CNTRL_3_PACKET_FORMAT_MSK, val));
}
static int axi_adc_ad408x_interface_data_align(struct iio_backend *back,
u32 timeout_us)
{
@@ -659,6 +688,7 @@ static const struct iio_backend_ops adi_ad408x_ops = {
.free_buffer = axi_adc_free_buffer,
.data_sample_trigger = axi_adc_data_sample_trigger,
.filter_type_set = axi_adc_ad408x_filter_type_set,
.data_size_set = axi_adc_ad408x_data_size_set,
.interface_data_align = axi_adc_ad408x_interface_data_align,
.num_lanes_set = axi_adc_num_lanes_set,
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
+33 -9
View File
@@ -227,6 +227,26 @@ static int ads7138_osr_to_bits(int osr)
return -EINVAL;
}
static int ads7138_read_statistics(const struct i2c_client *client, u8 reg,
u8 *out_values, u8 length)
{
int ret;
/* Disable statistics update so the value is not updated mid read */
ret = ads7138_i2c_clear_bit(client, ADS7138_REG_GENERAL_CFG,
ADS7138_GENERAL_CFG_STATS_EN);
if (ret)
return ret;
ret = ads7138_i2c_read_block(client, reg, out_values, length);
if (ret)
return ret;
/* Enable statistics update after read */
return ads7138_i2c_set_bit(client, ADS7138_REG_GENERAL_CFG,
ADS7138_GENERAL_CFG_STATS_EN);
}
static int ads7138_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -236,28 +256,32 @@ static int ads7138_read_raw(struct iio_dev *indio_dev,
u8 values[2];
switch (mask) {
/*
* Reading the statistics registers reinitializes them. This is
* unfortunate but necessary to prevent data races.
*/
case IIO_CHAN_INFO_RAW:
ret = ads7138_i2c_read_block(data->client,
ADS7138_REG_RECENT_LSB_CH(chan->channel),
values, ARRAY_SIZE(values));
ret = ads7138_read_statistics(data->client,
ADS7138_REG_RECENT_LSB_CH(chan->channel),
values, ARRAY_SIZE(values));
if (ret)
return ret;
*val = get_unaligned_le16(values);
return IIO_VAL_INT;
case IIO_CHAN_INFO_PEAK:
ret = ads7138_i2c_read_block(data->client,
ADS7138_REG_MAX_LSB_CH(chan->channel),
values, ARRAY_SIZE(values));
ret = ads7138_read_statistics(data->client,
ADS7138_REG_MAX_LSB_CH(chan->channel),
values, ARRAY_SIZE(values));
if (ret)
return ret;
*val = get_unaligned_le16(values);
return IIO_VAL_INT;
case IIO_CHAN_INFO_TROUGH:
ret = ads7138_i2c_read_block(data->client,
ADS7138_REG_MIN_LSB_CH(chan->channel),
values, ARRAY_SIZE(values));
ret = ads7138_read_statistics(data->client,
ADS7138_REG_MIN_LSB_CH(chan->channel),
values, ARRAY_SIZE(values));
if (ret)
return ret;
+5 -1
View File
@@ -412,7 +412,11 @@ static int atlas_buffer_postenable(struct iio_dev *indio_dev)
if (ret)
return ret;
return atlas_set_interrupt(data, true);
ret = atlas_set_interrupt(data, true);
if (ret)
pm_runtime_put_autosuspend(&data->client->dev);
return ret;
}
static int atlas_buffer_predisable(struct iio_dev *indio_dev)
+1
View File
@@ -552,6 +552,7 @@ config MCP4728
config MCP47FEB02
tristate "MCP47F(E/V)B01/02/04/08/11/12/14/18/21/22/24/28 DAC driver"
depends on I2C
select REGMAP_I2C
help
Say yes here if you want to build the driver for the Microchip:
- 8-bit DAC:
+1 -1
View File
@@ -590,7 +590,7 @@ static ssize_t ad3552r_hs_show_data_source_avail(struct file *f,
int i;
for (i = 0; i < ARRAY_SIZE(dbgfs_attr_source); i++) {
len += scnprintf(buf + len, PAGE_SIZE - len, "%s ",
len += scnprintf(buf + len, sizeof(buf) - len, "%s ",
dbgfs_attr_source[i]);
}
buf[len - 1] = '\n';
+1 -1
View File
@@ -83,7 +83,7 @@ static const struct of_device_id ad5446_i2c_of_ids[] = {
{ .compatible = "adi,ad5622", .data = &ad5622_chip_info },
{ }
};
MODULE_DEVICE_TABLE(OF, ad5446_i2c_of_ids);
MODULE_DEVICE_TABLE(of, ad5446_i2c_of_ids);
static struct i2c_driver ad5446_i2c_driver = {
.driver = {
+12 -5
View File
@@ -32,6 +32,7 @@ static int m62332_set_value(struct iio_dev *indio_dev, u8 val, int channel)
{
struct m62332_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
bool enabling, disabling;
u8 outbuf[2];
int res;
@@ -43,7 +44,10 @@ static int m62332_set_value(struct iio_dev *indio_dev, u8 val, int channel)
mutex_lock(&data->mutex);
if (val) {
enabling = val && !data->raw[channel];
disabling = !val && data->raw[channel];
if (enabling) {
res = regulator_enable(data->vcc);
if (res)
goto out;
@@ -52,14 +56,17 @@ static int m62332_set_value(struct iio_dev *indio_dev, u8 val, int channel)
res = i2c_master_send(client, outbuf, ARRAY_SIZE(outbuf));
if (res >= 0 && res != ARRAY_SIZE(outbuf))
res = -EIO;
if (res < 0)
if (res < 0) {
if (enabling)
regulator_disable(data->vcc);
goto out;
}
if (disabling)
regulator_disable(data->vcc);
data->raw[channel] = val;
if (!val)
regulator_disable(data->vcc);
mutex_unlock(&data->mutex);
return 0;
+18 -20
View File
@@ -47,9 +47,6 @@ struct iio_dmabuf_priv {
u64 context;
/* Spinlock used for locking the dma_fence */
spinlock_t lock;
struct dma_buf_attachment *attach;
struct sg_table *sgt;
enum dma_data_direction dir;
@@ -57,7 +54,12 @@ struct iio_dmabuf_priv {
};
struct iio_dma_fence {
/*
* Must remain the first member so the default release callback can pass
* the fence directly to dma_fence_free().
*/
struct dma_fence base;
spinlock_t lock; /* protects base */
struct iio_dmabuf_priv *priv;
struct work_struct work;
};
@@ -1619,12 +1621,16 @@ static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep)
wake_up(&buffer->pollq);
guard(mutex)(&buffer->dmabufs_mutex);
/* Close all attached DMABUFs */
list_for_each_entry_safe(priv, tmp, &buffer->dmabufs, entry) {
list_del_init(&priv->entry);
iio_buffer_dmabuf_put(priv->attach);
/*
* The mutex must be unlocked before iio_device_put(), which might drop the
* last reference and free the buffer.
*/
scoped_guard(mutex, &buffer->dmabufs_mutex) {
/* Close all attached DMABUFs */
list_for_each_entry_safe(priv, tmp, &buffer->dmabufs, entry) {
list_del_init(&priv->entry);
iio_buffer_dmabuf_put(priv->attach);
}
}
kfree(ib);
@@ -1702,7 +1708,6 @@ static int iio_buffer_attach_dmabuf(struct iio_dev_buffer_pair *ib,
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
priv->context = dma_fence_context_alloc(1);
dmabuf = dma_buf_get(fd);
@@ -1827,18 +1832,9 @@ iio_buffer_dma_fence_get_driver_name(struct dma_fence *fence)
return "iio";
}
static void iio_buffer_dma_fence_release(struct dma_fence *fence)
{
struct iio_dma_fence *iio_fence =
container_of(fence, struct iio_dma_fence, base);
kfree(iio_fence);
}
static const struct dma_fence_ops iio_buffer_dma_fence_ops = {
.get_driver_name = iio_buffer_dma_fence_get_driver_name,
.get_timeline_name = iio_buffer_dma_fence_get_driver_name,
.release = iio_buffer_dma_fence_release,
};
static int iio_buffer_enqueue_dmabuf(struct iio_dev_buffer_pair *ib,
@@ -1892,6 +1888,8 @@ static int iio_buffer_enqueue_dmabuf(struct iio_dev_buffer_pair *ib,
goto err_attachment_put;
}
spin_lock_init(&fence->lock);
fence->priv = priv;
seqno = atomic_add_return(1, &priv->seqno);
@@ -1902,7 +1900,7 @@ static int iio_buffer_enqueue_dmabuf(struct iio_dev_buffer_pair *ib,
* the dma_fence.
*/
dma_fence_init(&fence->base, &iio_buffer_dma_fence_ops,
&priv->lock, priv->context, seqno);
&fence->lock, priv->context, seqno);
ret = iio_dma_resv_lock(dmabuf, nonblock);
if (ret)
+8 -2
View File
@@ -669,7 +669,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 +677,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,
+1 -2
View File
@@ -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;
+11 -26
View File
@@ -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, &reg);
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;
+7 -2
View File
@@ -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, &regval);
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);
+1 -2
View File
@@ -845,7 +845,6 @@ static const struct iio_info dps310_info = {
static int dps310_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct dps310_data *data;
struct iio_dev *iio;
int rc;
@@ -858,7 +857,7 @@ static int dps310_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->lock);
iio->name = id->name;
iio->name = DPS310_DEV_NAME;
iio->channels = dps310_channels;
iio->num_channels = ARRAY_SIZE(dps310_channels);
iio->info = &dps310_info;
@@ -243,7 +243,7 @@ static int hid_temperature_probe(struct platform_device *pdev)
if (ret)
goto error_remove_trigger;
ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
ret = iio_device_register(indio_dev);
if (ret)
goto error_remove_callback;
@@ -263,6 +263,7 @@ static void hid_temperature_remove(struct platform_device *pdev)
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct temperature_state *temp_st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
}