diff options
Diffstat (limited to 'drivers/iio/magnetometer')
-rw-r--r-- | drivers/iio/magnetometer/Kconfig | 15 | ||||
-rw-r--r-- | drivers/iio/magnetometer/Makefile | 2 | ||||
-rw-r--r-- | drivers/iio/magnetometer/ak8974.c | 2 | ||||
-rw-r--r-- | drivers/iio/magnetometer/ak8975.c | 1 | ||||
-rw-r--r-- | drivers/iio/magnetometer/als31300.c | 5 | ||||
-rw-r--r-- | drivers/iio/magnetometer/bmc150_magn.c | 13 | ||||
-rw-r--r-- | drivers/iio/magnetometer/tlv493d.c | 526 | ||||
-rw-r--r-- | drivers/iio/magnetometer/tmag5273.c | 5 | ||||
-rw-r--r-- | drivers/iio/magnetometer/yamaha-yas530.c | 2 |
9 files changed, 548 insertions, 23 deletions
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 3debf1320ad1..81b812a29044 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -123,7 +123,7 @@ config HID_SENSOR_MAGNETOMETER_3D select IIO_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER - tristate "HID Magenetometer 3D" + tristate "HID Magnetometer 3D" help Say yes here to build support for the HID SENSOR Magnetometer 3D. @@ -173,6 +173,19 @@ config IIO_ST_MAGN_SPI_3AXIS To compile this driver as a module, choose M here. The module will be called st_magn_spi. +config INFINEON_TLV493D + tristate "Infineon TLV493D Low-Power 3D Magnetic Sensor" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here to add support for the Infineon TLV493D-A1B6 Low- + Power 3D Magnetic Sensor. + + This driver can also be compiled as a module. + To compile this driver as a module, choose M here: the module + will be called tlv493d. + config SENSORS_HMC5843 tristate select IIO_BUFFER diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index 9297723a97d8..dfe970fcacb8 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -23,6 +23,8 @@ st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o +obj-$(CONFIG_INFINEON_TLV493D) += tlv493d.o + obj-$(CONFIG_SENSORS_HMC5843) += hmc5843_core.o obj-$(CONFIG_SENSORS_HMC5843_I2C) += hmc5843_i2c.o obj-$(CONFIG_SENSORS_HMC5843_SPI) += hmc5843_spi.o diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 947fe8a475f2..68ece700c7ce 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -583,7 +583,6 @@ static int ak8974_measure_channel(struct ak8974 *ak8974, unsigned long address, *val = (s16)le16_to_cpu(hw_values[address]); out_unlock: mutex_unlock(&ak8974->lock); - pm_runtime_mark_last_busy(&ak8974->i2c->dev); pm_runtime_put_autosuspend(&ak8974->i2c->dev); return ret; @@ -678,7 +677,6 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev) out_unlock: mutex_unlock(&ak8974->lock); - pm_runtime_mark_last_busy(&ak8974->i2c->dev); pm_runtime_put_autosuspend(&ak8974->i2c->dev); } diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index a1e92b2abffd..3fd0171e5d69 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -775,7 +775,6 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) mutex_unlock(&data->lock); - pm_runtime_mark_last_busy(&data->client->dev); pm_runtime_put_autosuspend(&data->client->dev); /* Swap bytes and convert to valid range. */ diff --git a/drivers/iio/magnetometer/als31300.c b/drivers/iio/magnetometer/als31300.c index f72af829715f..2a2677428ed5 100644 --- a/drivers/iio/magnetometer/als31300.c +++ b/drivers/iio/magnetometer/als31300.c @@ -140,7 +140,6 @@ static int als31300_get_measure(struct als31300_data *data, *z = ALS31300_DATA_Z_GET(buf); out: - pm_runtime_mark_last_busy(data->dev); pm_runtime_put_autosuspend(data->dev); return ret; @@ -156,7 +155,6 @@ static int als31300_read_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case IIO_CHAN_INFO_PROCESSED: case IIO_CHAN_INFO_RAW: ret = als31300_get_measure(data, &t, &x, &y, &z); if (ret) @@ -373,7 +371,7 @@ static int als31300_probe(struct i2c_client *i2c) ret = devm_add_action_or_reset(dev, als31300_power_down, data); if (ret) - return dev_err_probe(dev, ret, "failed to add powerdown action\n"); + return ret; indio_dev->info = &als31300_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -401,7 +399,6 @@ static int als31300_probe(struct i2c_client *i2c) pm_runtime_set_autosuspend_delay(dev, 200); pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); ret = devm_iio_device_register(dev, indio_dev); diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index 761daead5ada..6a73f6e2f1f0 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -257,22 +257,17 @@ static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data, static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) { -#ifdef CONFIG_PM - int ret; + int ret = 0; - if (on) { + if (on) ret = pm_runtime_resume_and_get(data->dev); - } else { - pm_runtime_mark_last_busy(data->dev); - ret = pm_runtime_put_autosuspend(data->dev); - } - + else + pm_runtime_put_autosuspend(data->dev); if (ret < 0) { dev_err(data->dev, "failed to change power state to %d\n", on); return ret; } -#endif return 0; } diff --git a/drivers/iio/magnetometer/tlv493d.c b/drivers/iio/magnetometer/tlv493d.c new file mode 100644 index 000000000000..ec53fd40277b --- /dev/null +++ b/drivers/iio/magnetometer/tlv493d.c @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for the Infineon TLV493D Low-Power 3D Magnetic Sensor + * + * Copyright (C) 2025 Dixit Parmar <dixitparmar19@gmail.com> + */ + +#include <linux/array_size.h> +#include <linux/bits.h> +#include <linux/bitfield.h> +#include <linux/cleanup.h> +#include <linux/delay.h> +#include <linux/dev_printk.h> +#include <linux/i2c.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <linux/types.h> +#include <linux/units.h> + +#include <linux/iio/buffer.h> +#include <linux/iio/iio.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +/* + * TLV493D sensor I2C communication note: + * + * The sensor supports only direct byte-stream write starting from the + * register address 0x0. So for any modification to be made to any write + * registers, it must be written starting from the register address 0x0. + * I2C write operation should not contain the register address in the I2C + * frame, it should contain only raw byte stream for the write registers. + * I2C Frame: |S|SlaveAddr Wr|Ack|Byte[0]|Ack|Byte[1]|Ack|.....|Sp| + * + * Same as the write operation, reading from the sensor registers is also + * performed starting from the register address 0x0 for as many bytes as + * need to be read. + * I2C read operation should not contain the register address in the I2C frame. + * I2C Frame: |S|SlaveAddr Rd|Ack|Byte[0]|Ack|Byte[1]|Ack|.....|Sp| + */ + +#define TLV493D_RD_REG_BX 0x00 +#define TLV493D_RD_REG_BY 0x01 +#define TLV493D_RD_REG_BZ 0x02 +#define TLV493D_RD_REG_TEMP 0x03 +#define TLV493D_RD_REG_BX2 0x04 +#define TLV493D_RD_REG_BZ2 0x05 +#define TLV493D_RD_REG_TEMP2 0x06 +#define TLV493D_RD_REG_RES1 0x07 +#define TLV493D_RD_REG_RES2 0x08 +#define TLV493D_RD_REG_RES3 0x09 +#define TLV493D_RD_REG_MAX 0x0a + +#define TLV493D_WR_REG_MODE1 0x01 +#define TLV493D_WR_REG_MODE2 0x03 +#define TLV493D_WR_REG_MAX 0x04 + +#define TLV493D_BX_MAG_X_AXIS_MSB GENMASK(7, 0) +#define TLV493D_BX2_MAG_X_AXIS_LSB GENMASK(7, 4) +#define TLV493D_BY_MAG_Y_AXIS_MSB GENMASK(7, 0) +#define TLV493D_BX2_MAG_Y_AXIS_LSB GENMASK(3, 0) +#define TLV493D_BZ_MAG_Z_AXIS_MSB GENMASK(7, 0) +#define TLV493D_BZ2_MAG_Z_AXIS_LSB GENMASK(3, 0) +#define TLV493D_TEMP_TEMP_MSB GENMASK(7, 4) +#define TLV493D_TEMP2_TEMP_LSB GENMASK(7, 0) +#define TLV493D_TEMP_CHANNEL GENMASK(1, 0) +#define TLV493D_MODE1_MOD_LOWFAST GENMASK(1, 0) +#define TLV493D_MODE2_LP_PERIOD BIT(6) +#define TLV493D_RD_REG_RES1_WR_MASK GENMASK(4, 3) +#define TLV493D_RD_REG_RES2_WR_MASK GENMASK(7, 0) +#define TLV493D_RD_REG_RES3_WR_MASK GENMASK(4, 0) + +enum tlv493d_channels { + TLV493D_AXIS_X, + TLV493D_AXIS_Y, + TLV493D_AXIS_Z, + TLV493D_TEMPERATURE, +}; + +enum tlv493d_op_mode { + TLV493D_OP_MODE_POWERDOWN, + TLV493D_OP_MODE_FAST, + TLV493D_OP_MODE_LOWPOWER, + TLV493D_OP_MODE_ULTRA_LOWPOWER, + TLV493D_OP_MODE_MASTERCONTROLLED, +}; + +struct tlv493d_data { + struct i2c_client *client; + /* protects from simultaneous sensor access and register readings */ + struct mutex lock; + enum tlv493d_op_mode mode; + u8 wr_regs[TLV493D_WR_REG_MAX]; +}; + +/* + * Different mode has different measurement sampling time, this time is + * used in deriving the sleep and timeout while reading the data from + * sensor in polling. + * Power-down mode: No measurement. + * Fast mode: Freq:3.3 KHz. Measurement time:305 usec. + * Low-power mode: Freq:100 Hz. Measurement time:10 msec. + * Ultra low-power mode: Freq:10 Hz. Measurement time:100 msec. + * Master controlled mode: Freq:3.3 Khz. Measurement time:305 usec. + */ +static const u32 tlv493d_sample_rate_us[] = { + [TLV493D_OP_MODE_POWERDOWN] = 0, + [TLV493D_OP_MODE_FAST] = 305, + [TLV493D_OP_MODE_LOWPOWER] = 10 * USEC_PER_MSEC, + [TLV493D_OP_MODE_ULTRA_LOWPOWER] = 100 * USEC_PER_MSEC, + [TLV493D_OP_MODE_MASTERCONTROLLED] = 305, +}; + +static int tlv493d_write_all_regs(struct tlv493d_data *data) +{ + int ret; + struct device *dev = &data->client->dev; + + ret = i2c_master_send(data->client, data->wr_regs, ARRAY_SIZE(data->wr_regs)); + if (ret < 0) { + dev_err(dev, "i2c write registers failed, error: %d\n", ret); + return ret; + } + + return 0; +} + +static int tlv493d_set_operating_mode(struct tlv493d_data *data, enum tlv493d_op_mode mode) +{ + u8 *mode1_cfg = &data->wr_regs[TLV493D_WR_REG_MODE1]; + u8 *mode2_cfg = &data->wr_regs[TLV493D_WR_REG_MODE2]; + + switch (mode) { + case TLV493D_OP_MODE_POWERDOWN: + FIELD_MODIFY(TLV493D_MODE1_MOD_LOWFAST, mode1_cfg, 0); + FIELD_MODIFY(TLV493D_MODE2_LP_PERIOD, mode2_cfg, 0); + break; + + case TLV493D_OP_MODE_FAST: + FIELD_MODIFY(TLV493D_MODE1_MOD_LOWFAST, mode1_cfg, 1); + FIELD_MODIFY(TLV493D_MODE2_LP_PERIOD, mode2_cfg, 0); + break; + + case TLV493D_OP_MODE_LOWPOWER: + FIELD_MODIFY(TLV493D_MODE1_MOD_LOWFAST, mode1_cfg, 2); + FIELD_MODIFY(TLV493D_MODE2_LP_PERIOD, mode2_cfg, 1); + break; + + case TLV493D_OP_MODE_ULTRA_LOWPOWER: + FIELD_MODIFY(TLV493D_MODE1_MOD_LOWFAST, mode1_cfg, 2); + FIELD_MODIFY(TLV493D_MODE2_LP_PERIOD, mode2_cfg, 0); + break; + + case TLV493D_OP_MODE_MASTERCONTROLLED: + FIELD_MODIFY(TLV493D_MODE1_MOD_LOWFAST, mode1_cfg, 3); + FIELD_MODIFY(TLV493D_MODE2_LP_PERIOD, mode2_cfg, 0); + break; + } + + return tlv493d_write_all_regs(data); +} + +static s16 tlv493d_get_channel_data(u8 *b, enum tlv493d_channels ch) +{ + u16 val; + + switch (ch) { + case TLV493D_AXIS_X: + val = FIELD_GET(TLV493D_BX_MAG_X_AXIS_MSB, b[TLV493D_RD_REG_BX]) << 4 | + FIELD_GET(TLV493D_BX2_MAG_X_AXIS_LSB, b[TLV493D_RD_REG_BX2]) >> 4; + break; + case TLV493D_AXIS_Y: + val = FIELD_GET(TLV493D_BY_MAG_Y_AXIS_MSB, b[TLV493D_RD_REG_BY]) << 4 | + FIELD_GET(TLV493D_BX2_MAG_Y_AXIS_LSB, b[TLV493D_RD_REG_BX2]); + break; + case TLV493D_AXIS_Z: + val = FIELD_GET(TLV493D_BZ_MAG_Z_AXIS_MSB, b[TLV493D_RD_REG_BZ]) << 4 | + FIELD_GET(TLV493D_BZ2_MAG_Z_AXIS_LSB, b[TLV493D_RD_REG_BZ2]); + break; + case TLV493D_TEMPERATURE: + val = FIELD_GET(TLV493D_TEMP_TEMP_MSB, b[TLV493D_RD_REG_TEMP]) << 8 | + FIELD_GET(TLV493D_TEMP2_TEMP_LSB, b[TLV493D_RD_REG_TEMP2]); + break; + } + + return sign_extend32(val, 11); +} + +static int tlv493d_get_measurements(struct tlv493d_data *data, s16 *x, s16 *y, + s16 *z, s16 *t) +{ + u8 buff[7] = {}; + int err, ret; + struct device *dev = &data->client->dev; + u32 sleep_us = tlv493d_sample_rate_us[data->mode]; + + guard(mutex)(&data->lock); + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; + + /* + * Poll until data is valid. + * For a valid data TLV493D_TEMP_CHANNEL bit of TLV493D_RD_REG_TEMP + * should be set to 0. The sampling time depends on the sensor mode. + * Poll 3x the time of the sampling time. + */ + ret = read_poll_timeout(i2c_master_recv, err, + err || !FIELD_GET(TLV493D_TEMP_CHANNEL, buff[TLV493D_RD_REG_TEMP]), + sleep_us, 3 * sleep_us, false, data->client, buff, + ARRAY_SIZE(buff)); + if (ret) { + dev_err(dev, "i2c read poll timeout, error:%d\n", ret); + goto out_put_autosuspend; + } + if (err < 0) { + dev_err(dev, "i2c read data failed, error:%d\n", err); + ret = err; + goto out_put_autosuspend; + } + + *x = tlv493d_get_channel_data(buff, TLV493D_AXIS_X); + *y = tlv493d_get_channel_data(buff, TLV493D_AXIS_Y); + *z = tlv493d_get_channel_data(buff, TLV493D_AXIS_Z); + *t = tlv493d_get_channel_data(buff, TLV493D_TEMPERATURE); + +out_put_autosuspend: + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int tlv493d_init(struct tlv493d_data *data) +{ + int ret; + u8 buff[TLV493D_RD_REG_MAX]; + struct device *dev = &data->client->dev; + + /* + * The sensor initialization requires below steps to be followed, + * 1. Power-up sensor. + * 2. Read and store read-registers map (0x0-0x9). + * 3. Copy values from read reserved registers to write reserved fields + * (0x0-0x3). + * 4. Set operating mode. + * 5. Write to all registers. + */ + ret = i2c_master_recv(data->client, buff, ARRAY_SIZE(buff)); + if (ret < 0) + return dev_err_probe(dev, ret, "i2c read failed\n"); + + /* Write register 0x0 is reserved. Does not require to be updated.*/ + data->wr_regs[0] = 0; + data->wr_regs[1] = buff[TLV493D_RD_REG_RES1] & TLV493D_RD_REG_RES1_WR_MASK; + data->wr_regs[2] = buff[TLV493D_RD_REG_RES2] & TLV493D_RD_REG_RES2_WR_MASK; + data->wr_regs[3] = buff[TLV493D_RD_REG_RES3] & TLV493D_RD_REG_RES3_WR_MASK; + + ret = tlv493d_set_operating_mode(data, data->mode); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to set operating mode\n"); + + return 0; +} + +static int tlv493d_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, + int *val2, long mask) +{ + struct tlv493d_data *data = iio_priv(indio_dev); + s16 x, y, z, t; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = tlv493d_get_measurements(data, &x, &y, &z, &t); + if (ret) + return ret; + + switch (chan->address) { + case TLV493D_AXIS_X: + *val = x; + return IIO_VAL_INT; + case TLV493D_AXIS_Y: + *val = y; + return IIO_VAL_INT; + case TLV493D_AXIS_Z: + *val = z; + return IIO_VAL_INT; + case TLV493D_TEMPERATURE: + *val = t; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_MAGN: + /* + * Magnetic field scale: 0.0098 mTesla (i.e. 9.8 µT) + * Magnetic field in Gauss: mT * 10 = 0.098. + */ + *val = 98; + *val2 = 1000; + return IIO_VAL_FRACTIONAL; + case IIO_TEMP: + /* + * Temperature scale: 1.1 °C per LSB, expressed as 1100 m°C + * Returned as integer for IIO core to apply: + * temp = (raw + offset) * scale + */ + *val = 1100; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + /* + * Temperature offset includes sensor-specific raw offset + * plus compensation for +25°C bias in formula. + * offset = -raw_offset + (25000 / 1100) + * -340 + 22.72 = -317.28 + */ + *val = -31728; + *val2 = 100; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static irqreturn_t tlv493d_trigger_handler(int irq, void *ptr) +{ + int ret; + s16 x, y, z, t; + struct iio_poll_func *pf = ptr; + struct iio_dev *indio_dev = pf->indio_dev; + struct tlv493d_data *data = iio_priv(indio_dev); + struct device *dev = &data->client->dev; + struct { + s16 channels[3]; + s16 temperature; + aligned_s64 timestamp; + } scan; + + ret = tlv493d_get_measurements(data, &x, &y, &z, &t); + if (ret) { + dev_err(dev, "failed to read sensor data\n"); + goto out_trigger_notify; + } + + scan.channels[0] = x; + scan.channels[1] = y; + scan.channels[2] = z; + scan.temperature = t; + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), pf->timestamp); + +out_trigger_notify: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +#define TLV493D_AXIS_CHANNEL(axis, index) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ + } + +static const struct iio_chan_spec tlv493d_channels[] = { + TLV493D_AXIS_CHANNEL(X, TLV493D_AXIS_X), + TLV493D_AXIS_CHANNEL(Y, TLV493D_AXIS_Y), + TLV493D_AXIS_CHANNEL(Z, TLV493D_AXIS_Z), + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .address = TLV493D_TEMPERATURE, + .scan_index = TLV493D_TEMPERATURE, + .scan_type = { + .sign = 's', + .realbits = 12, + .storagebits = 16, + .endianness = IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const struct iio_info tlv493d_info = { + .read_raw = tlv493d_read_raw, +}; + +static const unsigned long tlv493d_scan_masks[] = { GENMASK(3, 0), 0 }; + +static int tlv493d_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct iio_dev *indio_dev; + struct tlv493d_data *data; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + ret = devm_mutex_init(dev, &data->lock); + if (ret) + return ret; + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, "failed to enable regulator\n"); + + /* + * Setting Sensor default operating mode to Master-Controlled mode since + * it performs measurement cycle only on-request and stays in Power-Down + * state until next cycle is initiated. + */ + data->mode = TLV493D_OP_MODE_MASTERCONTROLLED; + ret = tlv493d_init(data); + if (ret) + return dev_err_probe(dev, ret, "failed to initialize\n"); + + indio_dev->info = &tlv493d_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = client->name; + indio_dev->channels = tlv493d_channels; + indio_dev->num_channels = ARRAY_SIZE(tlv493d_channels); + indio_dev->available_scan_masks = tlv493d_scan_masks; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + tlv493d_trigger_handler, + NULL); + if (ret) + return dev_err_probe(dev, ret, "iio triggered buffer setup failed\n"); + + ret = pm_runtime_set_active(dev); + if (ret) + return ret; + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + pm_runtime_get_noresume(dev); + pm_runtime_set_autosuspend_delay(dev, 500); + pm_runtime_use_autosuspend(dev); + + pm_runtime_put_autosuspend(dev); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return dev_err_probe(dev, ret, "iio device register failed\n"); + + return 0; +} + +static int tlv493d_runtime_suspend(struct device *dev) +{ + struct tlv493d_data *data = iio_priv(dev_get_drvdata(dev)); + + return tlv493d_set_operating_mode(data, TLV493D_OP_MODE_POWERDOWN); +} + +static int tlv493d_runtime_resume(struct device *dev) +{ + struct tlv493d_data *data = iio_priv(dev_get_drvdata(dev)); + + return tlv493d_set_operating_mode(data, data->mode); +} + +static DEFINE_RUNTIME_DEV_PM_OPS(tlv493d_pm_ops, tlv493d_runtime_suspend, + tlv493d_runtime_resume, NULL); + +static const struct i2c_device_id tlv493d_id[] = { + { "tlv493d" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tlv493d_id); + +static const struct of_device_id tlv493d_of_match[] = { + { .compatible = "infineon,tlv493d-a1b6" }, + { } +}; +MODULE_DEVICE_TABLE(of, tlv493d_of_match); + +static struct i2c_driver tlv493d_driver = { + .driver = { + .name = "tlv493d", + .of_match_table = tlv493d_of_match, + .pm = pm_ptr(&tlv493d_pm_ops), + }, + .probe = tlv493d_probe, + .id_table = tlv493d_id, +}; +module_i2c_driver(tlv493d_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Infineon TLV493D Low-Power 3D Magnetic Sensor"); +MODULE_AUTHOR("Dixit Parmar <dixitparmar19@gmail.com>"); diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c index 2ca5c26f0091..2adc3c036ab4 100644 --- a/drivers/iio/magnetometer/tmag5273.c +++ b/drivers/iio/magnetometer/tmag5273.c @@ -287,7 +287,6 @@ static int tmag5273_read_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case IIO_CHAN_INFO_PROCESSED: case IIO_CHAN_INFO_RAW: ret = pm_runtime_resume_and_get(data->dev); if (ret < 0) @@ -295,7 +294,6 @@ static int tmag5273_read_raw(struct iio_dev *indio_dev, ret = tmag5273_get_measure(data, &t, &x, &y, &z, &angle, &magnitude); - pm_runtime_mark_last_busy(data->dev); pm_runtime_put_autosuspend(data->dev); if (ret) @@ -642,7 +640,7 @@ static int tmag5273_probe(struct i2c_client *i2c) */ ret = devm_add_action_or_reset(dev, tmag5273_power_down, data); if (ret) - return dev_err_probe(dev, ret, "failed to add powerdown action\n"); + return ret; ret = pm_runtime_set_active(dev); if (ret < 0) @@ -668,7 +666,6 @@ static int tmag5273_probe(struct i2c_client *i2c) indio_dev->channels = tmag5273_channels; indio_dev->num_channels = ARRAY_SIZE(tmag5273_channels); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); ret = devm_iio_device_register(dev, indio_dev); diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c index 340607111d9a..d49e37edcbed 100644 --- a/drivers/iio/magnetometer/yamaha-yas530.c +++ b/drivers/iio/magnetometer/yamaha-yas530.c @@ -623,7 +623,6 @@ static int yas5xx_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: pm_runtime_get_sync(yas5xx->dev); ret = ci->get_measure(yas5xx, &t, &x, &y, &z); - pm_runtime_mark_last_busy(yas5xx->dev); pm_runtime_put_autosuspend(yas5xx->dev); if (ret) return ret; @@ -664,7 +663,6 @@ static void yas5xx_fill_buffer(struct iio_dev *indio_dev) pm_runtime_get_sync(yas5xx->dev); ret = ci->get_measure(yas5xx, &t, &x, &y, &z); - pm_runtime_mark_last_busy(yas5xx->dev); pm_runtime_put_autosuspend(yas5xx->dev); if (ret) { dev_err(yas5xx->dev, "error refilling buffer\n"); |