summaryrefslogtreecommitdiff
path: root/drivers/iio/magnetometer
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/magnetometer')
-rw-r--r--drivers/iio/magnetometer/Kconfig15
-rw-r--r--drivers/iio/magnetometer/Makefile2
-rw-r--r--drivers/iio/magnetometer/ak8974.c2
-rw-r--r--drivers/iio/magnetometer/ak8975.c1
-rw-r--r--drivers/iio/magnetometer/als31300.c5
-rw-r--r--drivers/iio/magnetometer/bmc150_magn.c13
-rw-r--r--drivers/iio/magnetometer/tlv493d.c526
-rw-r--r--drivers/iio/magnetometer/tmag5273.c5
-rw-r--r--drivers/iio/magnetometer/yamaha-yas530.c2
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");