diff --git a/MAINTAINERS b/MAINTAINERS
index 78467ad7a8fe..d0183c09cc3f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20004,6 +20004,24 @@ F:	Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst
 F:	drivers/net/ethernet/qualcomm/rmnet/
 F:	include/linux/if_rmnet.h
 
+QUALCOMM SENSOR MANAGER IIO DRIVER
+M:	Yassine Oudjana <y.oudjana@protonmail.com>
+L:	linux-iio@vger.kernel.org
+L:	linux-arm-msm@vger.kernel.org
+S:	Maintained
+F:	drivers/iio/accel/qcom_smgr_accel.c
+F:	drivers/iio/common/qcom_smgr/Kconfig
+F:	drivers/iio/common/qcom_smgr/Makefile
+F:	drivers/iio/common/qcom_smgr/qcom_smgr.c
+F:	drivers/iio/common/qcom_smgr/qmi/Makefile
+F:	drivers/iio/common/qcom_smgr/qmi/sns_smgr.c
+F:	drivers/iio/common/qcom_smgr/qmi/sns_smgr.h
+F:	drivers/iio/gyro/qcom_smgr_gyro.c
+F:	drivers/iio/magnetometer/qcom_smgr_mag.c
+F:	drivers/iio/pressure/qcom_smgr_pressure.c
+F:	drivers/iio/proximity/qcom_smgr_prox.c
+F:	include/linux/iio/common/qcom_smgr.h
+
 QUALCOMM TRUST ZONE MEMORY ALLOCATOR
 M:	Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
 L:	linux-arm-msm@vger.kernel.org
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 8c3f7cf55d5f..d3253b856771 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -407,6 +407,16 @@ config IIO_CROS_EC_ACCEL_LEGACY
 	  Sensor data is retrieved through IO memory.
 	  Newer devices should use IIO_CROS_EC_SENSORS.
 
+config IIO_QCOM_SMGR_ACCEL
+	tristate "Qualcomm SSC Sensor Manager Accelerometer Sensor"
+	depends on IIO_QCOM_SMGR
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say yes here to get support for accelerometers connected to
+	  a Qualcomm Snapdragon Sensor Core and accessed through its
+	  Sensor Manager service.
+
 config IIO_ST_ACCEL_3AXIS
 	tristate "STMicroelectronics accelerometers 3-Axis Driver"
 	depends on (I2C || SPI_MASTER) && SYSFS
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index ca8569e25aba..5f7fcd88a502 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_STK8BA50)		+= stk8ba50.o
 
 obj-$(CONFIG_IIO_CROS_EC_ACCEL_LEGACY) += cros_ec_accel_legacy.o
 
+obj-$(CONFIG_IIO_QCOM_SMGR_ACCEL) += qcom_smgr_accel.o
+
 obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o
 
 obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
diff --git a/drivers/iio/accel/qcom_smgr_accel.c b/drivers/iio/accel/qcom_smgr_accel.c
new file mode 100644
index 000000000000..ce854312d1d9
--- /dev/null
+++ b/drivers/iio/accel/qcom_smgr_accel.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Sensor Manager accelerometer driver
+ *
+ * Copyright (c) 2022, Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+
+static const struct iio_chan_spec qcom_smgr_accel_iio_channels[] = {
+	{
+		.type = IIO_ACCEL,
+		.modified = true,
+		.channel2 = IIO_MOD_X,
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_ACCEL,
+		.modified = true,
+		.channel2 = IIO_MOD_Y,
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_ACCEL,
+		.modified = true,
+		.channel2 = IIO_MOD_Z,
+		.scan_index = 2,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_TIMESTAMP,
+		.channel = -1,
+		.scan_index = 3,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 32,
+			.storagebits = 64,
+			.endianness = IIO_LE,
+		},
+	},
+};
+
+static int qcom_smgr_accel_probe(struct platform_device *pdev)
+{
+	struct iio_dev *iio_dev;
+	struct qcom_smgr_iio_priv *priv;
+	int ret;
+
+	iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	priv = iio_priv(iio_dev);
+	priv->sensor = *(struct qcom_smgr_sensor **)pdev->dev.platform_data;
+	priv->sensor->iio_dev = iio_dev;
+
+	iio_dev->name = "qcom-smgr-accel";
+	iio_dev->info = &qcom_smgr_iio_info;
+	iio_dev->channels = qcom_smgr_accel_iio_channels;
+	iio_dev->num_channels = ARRAY_SIZE(qcom_smgr_accel_iio_channels);
+
+	ret = devm_iio_kfifo_buffer_setup(&pdev->dev, iio_dev,
+					  &qcom_smgr_buffer_ops);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to setup buffer: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	ret = devm_iio_device_register(&pdev->dev, iio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register IIO device: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv->sensor);
+
+	return 0;
+}
+
+static void qcom_smgr_accel_remove(struct platform_device *pdev)
+{
+	struct qcom_smgr_sensor *sensor = platform_get_drvdata(pdev);
+
+	sensor->iio_dev = NULL;
+}
+
+static const struct platform_device_id qcom_smgr_accel_ids[] = {
+	{ .name = "qcom-smgr-accel" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, qcom_smgr_accel_ids);
+
+static struct platform_driver qcom_smgr_accel_driver = {
+	.probe = qcom_smgr_accel_probe,
+	.remove = qcom_smgr_accel_remove,
+	.driver	= {
+		.name = "qcom_smgr_accel",
+	},
+	.id_table = qcom_smgr_accel_ids,
+};
+module_platform_driver(qcom_smgr_accel_driver);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm Sensor Manager accelerometer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
index 1ccb5ccf3706..0ad8b3972087 100644
--- a/drivers/iio/common/Kconfig
+++ b/drivers/iio/common/Kconfig
@@ -8,5 +8,6 @@ source "drivers/iio/common/hid-sensors/Kconfig"
 source "drivers/iio/common/inv_sensors/Kconfig"
 source "drivers/iio/common/ms_sensors/Kconfig"
 source "drivers/iio/common/scmi_sensors/Kconfig"
+source "drivers/iio/common/qcom_smgr/Kconfig"
 source "drivers/iio/common/ssp_sensors/Kconfig"
 source "drivers/iio/common/st_sensors/Kconfig"
diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
index d3e952239a62..f3f18484c91b 100644
--- a/drivers/iio/common/Makefile
+++ b/drivers/iio/common/Makefile
@@ -13,5 +13,6 @@ obj-y += hid-sensors/
 obj-y += inv_sensors/
 obj-y += ms_sensors/
 obj-y += scmi_sensors/
+obj-y += qcom_smgr/
 obj-y += ssp_sensors/
 obj-y += st_sensors/
diff --git a/drivers/iio/common/qcom_smgr/Kconfig b/drivers/iio/common/qcom_smgr/Kconfig
new file mode 100644
index 000000000000..da1965185001
--- /dev/null
+++ b/drivers/iio/common/qcom_smgr/Kconfig
@@ -0,0 +1,16 @@
+#
+# Qualcomm Sensor Manager IIO
+#
+
+config IIO_QCOM_SMGR
+	tristate "Qualcomm SSC Sensor Manager"
+	depends on ARCH_QCOM
+	depends on QCOM_RPROC_COMMON
+	select QCOM_QMI_HELPERS
+	select IIO_BUFFER
+	help
+	  Say yes here to build core support for the Sensor Manager (SMGR)
+	  service provided by the Qualcomm Snapdragon Sensor Core (SSC).
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called smgr.
diff --git a/drivers/iio/common/qcom_smgr/Makefile b/drivers/iio/common/qcom_smgr/Makefile
new file mode 100644
index 000000000000..84554cedd2e5
--- /dev/null
+++ b/drivers/iio/common/qcom_smgr/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Qualcomm Sensor Manager driver
+#
+
+obj-y += qmi/
+
+obj-$(CONFIG_IIO_QCOM_SMGR)	+= qcom_smgr.o
diff --git a/drivers/iio/common/qcom_smgr/qcom_smgr.c b/drivers/iio/common/qcom_smgr/qcom_smgr.c
new file mode 100644
index 000000000000..8d46be11d5b6
--- /dev/null
+++ b/drivers/iio/common/qcom_smgr/qcom_smgr.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Sensor Manager core driver
+ *
+ * Copyright (c) 2021, Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/iio/iio.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc/qcom_rproc.h>
+#include <linux/soc/qcom/qmi.h>
+#include <linux/soc/qcom/qrtr.h>
+#include <linux/types.h>
+#include <net/sock.h>
+
+#include "qmi/sns_smgr.h"
+
+#define SMGR_TICKS_PER_SECOND		32768
+#define SMGR_REPORT_RATE_HZ		(SMGR_TICKS_PER_SECOND * 2)
+#define SMGR_VALUE_DIV			65536
+
+struct qcom_smgr {
+	struct device *dev;
+
+	struct qmi_handle sns_smgr_hdl;
+	struct sockaddr_qrtr sns_smgr_info;
+	struct work_struct sns_smgr_work;
+
+	u8 sensor_count;
+	struct qcom_smgr_sensor *sensors;
+};
+
+static const char *const qcom_smgr_sensor_type_platform_names[] = {
+	[SNS_SMGR_SENSOR_TYPE_ACCEL] = "qcom-smgr-accel",
+	[SNS_SMGR_SENSOR_TYPE_GYRO] = "qcom-smgr-gyro",
+	[SNS_SMGR_SENSOR_TYPE_MAG] = "qcom-smgr-mag",
+	[SNS_SMGR_SENSOR_TYPE_PROX_LIGHT] = "qcom-smgr-prox-light",
+	[SNS_SMGR_SENSOR_TYPE_PRESSURE] = "qcom-smgr-pressure",
+	[SNS_SMGR_SENSOR_TYPE_HALL_EFFECT] = "qcom-smgr-hall-effect"
+};
+
+static void qcom_smgr_unregister_sensor(void *data)
+{
+	struct platform_device *pdev = data;
+
+	platform_device_unregister(pdev);
+}
+
+static int qcom_smgr_register_sensor(struct qcom_smgr *smgr,
+				     struct qcom_smgr_sensor *sensor)
+{
+	struct platform_device *pdev;
+	const char *name = qcom_smgr_sensor_type_platform_names[sensor->type];
+
+	pdev = platform_device_register_data(smgr->dev, name, sensor->id,
+					     &sensor, sizeof(sensor));
+	if (IS_ERR(pdev)) {
+		dev_err(smgr->dev, "Failed to register %s: %pe\n", name, pdev);
+		return PTR_ERR(pdev);
+	}
+
+	return devm_add_action_or_reset(smgr->dev, qcom_smgr_unregister_sensor,
+					pdev);
+}
+
+static int qcom_smgr_request_all_sensor_info(struct qcom_smgr *smgr,
+					     struct qcom_smgr_sensor **sensors)
+{
+	struct sns_smgr_all_sensor_info_resp resp = {};
+	struct qmi_txn txn;
+	u8 i;
+	int ret;
+
+	dev_dbg(smgr->dev, "Getting available sensors\n");
+
+	ret = qmi_txn_init(&smgr->sns_smgr_hdl, &txn,
+			   sns_smgr_all_sensor_info_resp_ei, &resp);
+	if (ret < 0) {
+		dev_err(smgr->dev, "Failed to initialize QMI TXN: %d\n", ret);
+		return ret;
+	}
+
+	ret = qmi_send_request(&smgr->sns_smgr_hdl, &smgr->sns_smgr_info, &txn,
+			       SNS_SMGR_ALL_SENSOR_INFO_MSG_ID,
+			       SNS_SMGR_ALL_SENSOR_INFO_REQ_MAX_LEN, NULL,
+			       NULL);
+	if (ret) {
+		dev_err(smgr->dev,
+			"Failed to send available sensors request: %d\n", ret);
+		qmi_txn_cancel(&txn);
+		return ret;
+	}
+
+	ret = qmi_txn_wait(&txn, 5 * HZ);
+	if (ret < 0)
+		return ret;
+
+	/* Check the response */
+	if (resp.result) {
+		dev_err(smgr->dev, "Available sensors request failed: 0x%x\n",
+			resp.result);
+		return -EREMOTEIO;
+	}
+
+	*sensors = devm_kzalloc(smgr->dev,
+				sizeof(struct qcom_smgr_sensor) * resp.item_len,
+				GFP_KERNEL);
+
+	for (i = 0; i < resp.item_len; ++i) {
+		(*sensors)[i].id = resp.items[i].id;
+		(*sensors)[i].type =
+			sns_smgr_sensor_type_from_str(resp.items[i].type);
+	}
+
+	return resp.item_len;
+}
+
+static int qcom_smgr_request_single_sensor_info(struct qcom_smgr *smgr,
+						struct qcom_smgr_sensor *sensor)
+{
+	struct sns_smgr_single_sensor_info_req req = {
+		.sensor_id = sensor->id,
+	};
+	struct sns_smgr_single_sensor_info_resp resp = {};
+	struct qmi_txn txn;
+	u8 i;
+	int ret;
+
+	dev_vdbg(smgr->dev, "Getting single sensor info for ID 0x%02x\n",
+		 sensor->id);
+
+	ret = qmi_txn_init(&smgr->sns_smgr_hdl, &txn,
+			   sns_smgr_single_sensor_info_resp_ei, &resp);
+	if (ret < 0) {
+		dev_err(smgr->dev, "Failed to initialize QMI transaction: %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = qmi_send_request(&smgr->sns_smgr_hdl, &smgr->sns_smgr_info, &txn,
+			       SNS_SMGR_SINGLE_SENSOR_INFO_MSG_ID,
+			       SNS_SMGR_SINGLE_SENSOR_INFO_REQ_MAX_LEN,
+			       sns_smgr_single_sensor_info_req_ei, &req);
+	if (ret < 0) {
+		dev_err(smgr->dev, "Failed to send sensor data request: %d\n",
+			ret);
+		qmi_txn_cancel(&txn);
+		return ret;
+	}
+
+	ret = qmi_txn_wait(&txn, 5 * HZ);
+	if (ret < 0)
+		return ret;
+
+	/* Check the response */
+	if (resp.result) {
+		dev_err(smgr->dev, "Single sensor info request failed: 0x%x\n",
+			resp.result);
+		return -EREMOTEIO;
+	}
+
+	sensor->data_type_count = resp.data_type_len;
+	sensor->data_types =
+		devm_kzalloc(smgr->dev,
+			     sizeof(struct qcom_smgr_data_type_item) *
+				     sensor->data_type_count,
+			     GFP_KERNEL);
+	if (!sensor->data_types)
+		return -ENOMEM;
+
+	for (i = 0; i < sensor->data_type_count; ++i) {
+		sensor->data_types[i].name = devm_kstrdup_const(
+			smgr->dev, resp.data_types[i].name, GFP_KERNEL);
+		sensor->data_types[i].vendor = devm_kstrdup_const(
+			smgr->dev, resp.data_types[i].vendor, GFP_KERNEL);
+
+		sensor->data_types[i].range = resp.data_types[i].range;
+
+		sensor->data_types[i].native_sample_rate_count =
+			resp.native_sample_rates[i].rate_count;
+		if (sensor->data_types[i].native_sample_rate_count) {
+			sensor->data_types[i]
+				.native_sample_rates = devm_kmemdup_array(
+				smgr->dev, resp.native_sample_rates[i].rates,
+				sensor->data_types[i].native_sample_rate_count,
+				sizeof(u16), GFP_KERNEL);
+			if (!sensor->data_types[i].native_sample_rates)
+				return -ENOMEM;
+		}
+
+		sensor->data_types[i].max_sample_rate =
+			resp.data_types[i].max_sample_rate_hz;
+	}
+
+	return 0;
+}
+
+static int qcom_smgr_request_buffering(struct qcom_smgr *smgr,
+				       struct qcom_smgr_sensor *sensor,
+				       bool enable)
+{
+	struct sns_smgr_buffering_req req = {
+		/*
+		 * Reuse sensor ID as a report ID to avoid having to keep track
+		 * of a separate set of IDs
+		 */
+		.report_id = sensor->id,
+		.notify_suspend_valid = false
+	};
+	struct sns_smgr_buffering_resp resp = {};
+	struct qmi_txn txn;
+	u16 sample_rate = 0;
+	int ret;
+
+	if (enable) {
+		req.action = SNS_SMGR_BUFFERING_ACTION_ADD;
+
+		/*
+		 * Report rate and sample rate can be configured separately.
+		 * The former is the rate at which buffering report indications
+		 * are sent, while the latter is the actual sample rate of the
+		 * sensor. If report rate is set lower than sample rate,
+		 * multiple samples can be bundled and sent in one report.
+		 * A report cannot have 0 samples, therefore report rate cannot
+		 * be higher than sample rate.
+		 *
+		 * Fow now we default to the maximum sample rate and set the
+		 * report rate such that every report contains only 1 sample.
+		 * This gives us the lowest latency.
+		 */
+		if (sensor->data_types[0].native_sample_rates)
+			sample_rate = sensor->data_types[0].native_sample_rates
+					[sensor->data_types[0]
+						 .native_sample_rate_count - 1];
+
+		/*
+		 * SMGR may support a lower maximum sample rate than natively
+		 * supported by the sensor.
+		 */
+		if (sample_rate == 0 ||
+		    sample_rate > sensor->data_types[0].max_sample_rate)
+			sample_rate = sensor->data_types[0].max_sample_rate;
+
+		req.report_rate = sample_rate * SMGR_REPORT_RATE_HZ;
+
+		req.item_len = 1;
+		req.items[0].sensor_id = sensor->id;
+		req.items[0].data_type = SNS_SMGR_DATA_TYPE_PRIMARY;
+
+		req.items[0].sampling_rate = sample_rate;
+
+		/*
+		 * Unknown fields set to values frequently seen in dumps and
+		 * known to be working (although many different random values
+		 * appear to not cause any trouble).
+		 */
+		req.items[0].val1 = 3;
+		req.items[0].val2 = 1;
+	} else
+		req.action = SNS_SMGR_BUFFERING_ACTION_DELETE;
+
+	ret = qmi_txn_init(&smgr->sns_smgr_hdl, &txn,
+			   sns_smgr_buffering_resp_ei, &resp);
+	if (ret < 0) {
+		dev_err(smgr->dev, "Failed to initialize QMI TXN: %d\n", ret);
+		return ret;
+	}
+
+	ret = qmi_send_request(&smgr->sns_smgr_hdl, &smgr->sns_smgr_info, &txn,
+			       SNS_SMGR_BUFFERING_MSG_ID,
+			       SNS_SMGR_BUFFERING_REQ_MAX_LEN,
+			       sns_smgr_buffering_req_ei, &req);
+	if (ret < 0) {
+		dev_err(smgr->dev, "Failed to send buffering request: %d\n",
+			ret);
+		qmi_txn_cancel(&txn);
+		return ret;
+	}
+
+	ret = qmi_txn_wait(&txn, 5 * HZ);
+	if (ret < 0)
+		return ret;
+
+	/* Check the response */
+	if (resp.result) {
+		dev_err(smgr->dev, "Buffering request failed: 0x%x\n",
+			resp.result);
+		return -EREMOTEIO;
+	}
+
+	/* Keep track of requested sample rate */
+	sensor->data_types[0].cur_sample_rate = sample_rate;
+
+	return 0;
+}
+
+static void qcom_smgr_buffering_report_handler(struct qmi_handle *hdl,
+					       struct sockaddr_qrtr *sq,
+					       struct qmi_txn *txn,
+					       const void *data)
+{
+	struct qcom_smgr *smgr =
+		container_of(hdl, struct qcom_smgr, sns_smgr_hdl);
+	struct sns_smgr_buffering_report_ind *ind =
+		(struct sns_smgr_buffering_report_ind *)data;
+	struct qcom_smgr_sensor *sensor;
+	u8 i;
+
+	for (i = 0; i < smgr->sensor_count; ++i) {
+		sensor = &smgr->sensors[i];
+
+		/* Find sensor matching report */
+		if (sensor->id != ind->report_id)
+			continue;
+
+		if (!sensor->iio_dev)
+			/* Corresponding driver was unloaded. Ignore remaining reports. */
+			return;
+
+		/*
+		 * Since we are matching report rate with sample rate, we only
+		 * get a single sample in every report.
+		 */
+		iio_push_to_buffers_with_timestamp(sensor->iio_dev,
+						   ind->samples[0].values,
+						   ind->metadata.timestamp);
+
+		break;
+	}
+}
+
+static const struct qmi_msg_handler qcom_smgr_msg_handlers[] = {
+	{
+		.type = QMI_INDICATION,
+		.msg_id = SNS_SMGR_BUFFERING_REPORT_MSG_ID,
+		.ei = sns_smgr_buffering_report_ind_ei,
+		.decoded_size = sizeof(struct sns_smgr_buffering_report_ind),
+		.fn = qcom_smgr_buffering_report_handler,
+	},
+	{}
+};
+
+static int qcom_smgr_sensor_postenable(struct iio_dev *iio_dev)
+{
+	struct qcom_smgr *smgr = dev_get_drvdata(iio_dev->dev.parent->parent);
+	struct qcom_smgr_iio_priv *priv = iio_priv(iio_dev);
+	struct qcom_smgr_sensor *sensor = priv->sensor;
+
+	return qcom_smgr_request_buffering(smgr, sensor, true);
+}
+
+static int qcom_smgr_sensor_postdisable(struct iio_dev *iio_dev)
+{
+	struct qcom_smgr *smgr = dev_get_drvdata(iio_dev->dev.parent->parent);
+	struct qcom_smgr_iio_priv *priv = iio_priv(iio_dev);
+	struct qcom_smgr_sensor *sensor = priv->sensor;
+
+	return qcom_smgr_request_buffering(smgr, sensor, false);
+}
+
+const struct iio_buffer_setup_ops qcom_smgr_buffer_ops = {
+	.postenable = &qcom_smgr_sensor_postenable,
+	.postdisable = &qcom_smgr_sensor_postdisable
+};
+EXPORT_SYMBOL_GPL(qcom_smgr_buffer_ops);
+
+static int qcom_smgr_iio_read_raw(struct iio_dev *iio_dev,
+				  struct iio_chan_spec const *chan, int *val,
+				  int *val2, long mask)
+{
+	struct qcom_smgr_iio_priv *priv = iio_priv(iio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = priv->sensor->data_types[0].cur_sample_rate;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			/*
+			 * Proximity value is reported as (SMGR_VALUE_DIV - x)/SMGR_VALUE_DIV of
+			 * the sensor range. As with sensor values, range is also reported as range
+			 * in meters * SMGR_VALUE_DIV. Proximity in meters can be calculated as
+			 * such:
+			 *
+			 * proximity = -value * range / SMGR_VALUE_DIV**2
+			 *
+			 * Since our denominator (val2) is an int, we cannot fit SMGR_VALUE_DIV**2.
+			 * Without losing too much accuracy, we can instead divide by 2 in the
+			 * numerator and denominator, and move the -1 coefficient to the
+			 * denominator. This way we can exactly fit within the lower bound of int.
+			 */
+			*val = priv->sensor->data_types[0].range / 2;
+			*val2 = -SMGR_VALUE_DIV / 2 * SMGR_VALUE_DIV;
+			return IIO_VAL_FRACTIONAL;
+		default:
+			/*
+			 * Sensor values are generally reported as 1/SMGR_VALUE_DIVths of the
+			 * corresponding unit.
+			 */
+			*val = 1;
+			*val2 = SMGR_VALUE_DIV;
+			return IIO_VAL_FRACTIONAL;
+		}
+	case IIO_CHAN_INFO_OFFSET:
+		/*
+		 * Proximity values are inverted and start from the upper bound as explained above.
+		 * No other channel types have an offset.
+		 */
+		*val = priv->sensor->data_types[0].range;
+		*val2 = SMGR_VALUE_DIV;
+		return IIO_VAL_FRACTIONAL;
+	}
+
+	return -EINVAL;
+}
+
+static int qcom_smgr_iio_write_raw(struct iio_dev *iio_dev,
+				   struct iio_chan_spec const *chan, int val,
+				   int val2, long mask)
+{
+	struct qcom_smgr_iio_priv *priv = iio_priv(iio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		priv->sensor->data_types[0].cur_sample_rate = val;
+
+		/*
+		 * Send new SMGR buffering request with updated rates
+		 * if buffer is enabled
+		 */
+		if (iio_buffer_enabled(iio_dev))
+			return iio_dev->setup_ops->postenable(iio_dev);
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int qcom_smgr_iio_read_avail(struct iio_dev *iio_dev,
+				    struct iio_chan_spec const *chan,
+				    const int **vals, int *type, int *length,
+				    long mask)
+{
+	struct qcom_smgr_iio_priv *priv = iio_priv(iio_dev);
+	const int samp_freq_vals[3] = {
+		1, 1, priv->sensor->data_types[0].cur_sample_rate
+	};
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*type = IIO_VAL_INT;
+		*vals = samp_freq_vals;
+		*length = ARRAY_SIZE(samp_freq_vals);
+		return IIO_AVAIL_RANGE;
+	}
+
+	return -EINVAL;
+}
+
+const struct iio_info qcom_smgr_iio_info = {
+	.read_raw = qcom_smgr_iio_read_raw,
+	.write_raw = qcom_smgr_iio_write_raw,
+	.read_avail = qcom_smgr_iio_read_avail,
+};
+EXPORT_SYMBOL_GPL(qcom_smgr_iio_info);
+
+/* SMGR reports values for 3-axis sensors in north-east-down coordinates */
+static const struct iio_mount_matrix qcom_smgr_iio_mount_matrix = {
+	.rotation = {
+		"0", "-1", "0",
+		"-1", "0", "0",
+		"0", "0", "1"
+	}
+};
+
+static const struct iio_mount_matrix *
+qcom_smgr_iio_get_mount_matrix(const struct iio_dev *iio_dev,
+			       const struct iio_chan_spec *chan)
+{
+	return &qcom_smgr_iio_mount_matrix;
+}
+
+const struct iio_chan_spec_ext_info qcom_smgr_iio_ext_info[] = {
+	IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, qcom_smgr_iio_get_mount_matrix),
+	{}
+};
+EXPORT_SYMBOL_GPL(qcom_smgr_iio_ext_info);
+
+static int qcom_smgr_probe(struct qrtr_device *qdev)
+{
+	struct qcom_smgr *smgr;
+	int i, j;
+	int ret;
+
+	smgr = devm_kzalloc(&qdev->dev, sizeof(*smgr), GFP_KERNEL);
+	if (!smgr)
+		return -ENOMEM;
+
+	smgr->dev = &qdev->dev;
+
+	smgr->sns_smgr_info.sq_family = AF_QIPCRTR;
+	smgr->sns_smgr_info.sq_node = qdev->node;
+	smgr->sns_smgr_info.sq_port = qdev->port;
+
+	dev_set_drvdata(&qdev->dev, smgr);
+
+	ret = qmi_handle_init(&smgr->sns_smgr_hdl,
+			      SNS_SMGR_SINGLE_SENSOR_INFO_RESP_MAX_LEN, NULL,
+			      qcom_smgr_msg_handlers);
+	if (ret < 0) {
+		dev_err(smgr->dev,
+			"Failed to initialize sensor manager handle: %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = qcom_smgr_request_all_sensor_info(smgr, &smgr->sensors);
+	if (ret < 0) {
+		dev_err(smgr->dev, "Failed to get available sensors: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+	smgr->sensor_count = ret;
+
+	/* Get primary and secondary sensors from each sensor ID */
+	for (i = 0; i < smgr->sensor_count; i++) {
+		ret = qcom_smgr_request_single_sensor_info(smgr,
+							   &smgr->sensors[i]);
+		if (ret < 0) {
+			dev_err(smgr->dev,
+				"Failed to get sensors from ID 0x%02x: %pe\n",
+				smgr->sensors[i].id, ERR_PTR(ret));
+			return ret;
+		}
+
+		for (j = 0; j < smgr->sensors[i].data_type_count; j++) {
+			/* Default to maximum sample rate */
+			smgr->sensors[i].data_types->cur_sample_rate =
+				smgr->sensors[i].data_types->max_sample_rate;
+
+			dev_dbg(smgr->dev, "0x%02x,%d: %s %s\n",
+				smgr->sensors[i].id, j,
+				smgr->sensors[i].data_types[j].vendor,
+				smgr->sensors[i].data_types[j].name);
+		}
+
+		qcom_smgr_register_sensor(smgr, &smgr->sensors[i]);
+	}
+
+	return 0;
+}
+
+static void qcom_smgr_remove(struct qrtr_device *qdev)
+{
+	struct qcom_smgr *smgr = dev_get_drvdata(&qdev->dev);
+
+	qmi_handle_release(&smgr->sns_smgr_hdl);
+}
+
+static const struct qrtr_device_id qcom_smgr_qrtr_match[] = {
+	{
+		.service = SNS_SMGR_QMI_SVC_ID,
+		.instance = QRTR_INSTANCE(SNS_SMGR_QMI_SVC_V1,
+					  SNS_SMGR_QMI_INS_ID)
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(qrtr, qcom_smgr_qrtr_match);
+
+static struct qrtr_driver qcom_smgr_driver = {
+	.probe = qcom_smgr_probe,
+	.remove = qcom_smgr_remove,
+	.id_table = qcom_smgr_qrtr_match,
+	.driver	= {
+		.name = "qcom_smgr",
+	},
+};
+module_qrtr_driver(qcom_smgr_driver);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm Sensor Manager driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/common/qcom_smgr/qmi/Makefile b/drivers/iio/common/qcom_smgr/qmi/Makefile
new file mode 100644
index 000000000000..e5722f0f8f68
--- /dev/null
+++ b/drivers/iio/common/qcom_smgr/qmi/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_IIO_QCOM_SMGR)	+= sns_smgr.o
diff --git a/drivers/iio/common/qcom_smgr/qmi/sns_smgr.c b/drivers/iio/common/qcom_smgr/qmi/sns_smgr.c
new file mode 100644
index 000000000000..624e3074a051
--- /dev/null
+++ b/drivers/iio/common/qcom_smgr/qmi/sns_smgr.c
@@ -0,0 +1,711 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * QMI element info arrays and helper functions for Qualcomm Sensor Manager
+ *
+ * Copyright (c) 2021, Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/module.h>
+#include <linux/soc/qcom/qmi.h>
+#include <linux/types.h>
+
+#include "sns_smgr.h"
+
+static const struct qmi_elem_info sns_smgr_all_sensor_info_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_all_sensor_info, id),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_all_sensor_info, id),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_all_sensor_info, type_len),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_all_sensor_info, type_len),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = SNS_SMGR_SENSOR_TYPE_MAX_LEN,
+		.elem_size = sizeof(char),
+		.array_type = VAR_LEN_ARRAY,
+		.offset = offsetof(struct sns_smgr_all_sensor_info, type),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+
+const struct qmi_elem_info sns_smgr_all_sensor_info_resp_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_all_sensor_info_resp,
+					  result),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x02,
+		.offset =
+			offsetof(struct sns_smgr_all_sensor_info_resp, result),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_all_sensor_info_resp,
+					  item_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x03,
+		.offset = offsetof(struct sns_smgr_all_sensor_info_resp,
+				   item_len),
+	},
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len = SNS_SMGR_ALL_SENSOR_INFO_MAX_LEN,
+		.elem_size = sizeof(struct sns_smgr_all_sensor_info),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x03,
+		.offset = offsetof(struct sns_smgr_all_sensor_info_resp, items),
+		.ei_array = sns_smgr_all_sensor_info_ei,
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+EXPORT_SYMBOL_GPL(sns_smgr_all_sensor_info_resp_ei);
+
+const struct qmi_elem_info sns_smgr_single_sensor_info_req_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_req, sensor_id),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x01,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_req,
+				   sensor_id),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+EXPORT_SYMBOL_GPL(sns_smgr_single_sensor_info_req_ei);
+
+static const struct qmi_elem_info sns_smgr_single_sensor_info_data_type_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type,
+			sensor_id),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   sensor_id),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type,
+			data_type),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   data_type),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type, name_len),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   name_len),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 0xff,
+		.elem_size = sizeof(char),
+		.array_type = VAR_LEN_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   name),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type,
+			vendor_len),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   vendor_len),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 0xff,
+		.elem_size = sizeof(char),
+		.array_type = VAR_LEN_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   vendor),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type, val1),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   val1),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type,
+			max_sample_rate_hz),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   max_sample_rate_hz),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type, val2),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   val2),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type,
+			current_ua),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   current_ua),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type, range),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   range),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_data_type,
+			resolution),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_data_type,
+				   resolution),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+
+static const struct qmi_elem_info sns_smgr_single_sensor_info_native_sample_rates_ei[] = {
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_native_sample_rates, rate_count),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_native_sample_rates,
+				   rate_count),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = SNS_SMGR_NATIVE_SAMPLE_RATES_MAX_LEN,
+		.elem_size = sizeof(u16),
+		.array_type = VAR_LEN_ARRAY,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_native_sample_rates,
+				   rates),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+
+const struct qmi_elem_info sns_smgr_single_sensor_info_resp_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_resp, result),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x02,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   result),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_resp, data_type_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x03,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data_type_len),
+	},
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len = SNS_SMGR_DATA_TYPE_COUNT,
+		.elem_size =
+			sizeof(struct sns_smgr_single_sensor_info_data_type),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x03,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data_types),
+		.ei_array = sns_smgr_single_sensor_info_data_type_ei,
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_resp, data1_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x10,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data1_len),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = SNS_SMGR_DATA_TYPE_COUNT,
+		.elem_size = sizeof(u32),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x10,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data1),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_resp, data2),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x11,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data2),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_resp, data3_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x12,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data3_len),
+	},
+	{
+		.data_type = QMI_UNSIGNED_8_BYTE,
+		.elem_len = SNS_SMGR_DATA_TYPE_COUNT,
+		.elem_size = sizeof(u64),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x12,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data3),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_resp,
+			native_sample_rates_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x13,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   native_sample_rates_len),
+	},
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len = SNS_SMGR_DATA_TYPE_COUNT,
+		.elem_size = sizeof(
+			struct sns_smgr_single_sensor_info_native_sample_rates),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x13,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   native_sample_rates),
+		.ei_array = sns_smgr_single_sensor_info_native_sample_rates_ei,
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_single_sensor_info_resp, data5_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x14,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data5_len),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = SNS_SMGR_DATA_TYPE_COUNT,
+		.elem_size = sizeof(u32),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x14,
+		.offset = offsetof(struct sns_smgr_single_sensor_info_resp,
+				   data5),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+EXPORT_SYMBOL_GPL(sns_smgr_single_sensor_info_resp_ei);
+
+static const struct qmi_elem_info sns_smgr_buffering_req_item_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req_item,
+					  sensor_id),
+		.array_type = NO_ARRAY,
+		.offset =
+			offsetof(struct sns_smgr_buffering_req_item, sensor_id),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req_item,
+					  data_type),
+		.array_type = NO_ARRAY,
+		.offset =
+			offsetof(struct sns_smgr_buffering_req_item, data_type),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req_item,
+					  val1),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_req_item,
+				   val1),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req_item,
+					  sampling_rate),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_req_item,
+				   sampling_rate),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req_item,
+					  val2),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_req_item,
+				   val2),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+
+static const struct qmi_elem_info sns_smgr_buffering_req_notify_suspend_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_req_notify_suspend,
+			proc_type),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_req_notify_suspend,
+				   proc_type),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_req_notify_suspend,
+			send_indications_during_suspend),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_req_notify_suspend,
+				   send_indications_during_suspend),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+
+const struct qmi_elem_info sns_smgr_buffering_req_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_buffering_req, report_id),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x01,
+		.offset = offsetof(struct sns_smgr_buffering_req, report_id),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_buffering_req, action),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x02,
+		.offset = offsetof(struct sns_smgr_buffering_req, action),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req,
+					  report_rate),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x03,
+		.offset = offsetof(struct sns_smgr_buffering_req, report_rate),
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_buffering_req, item_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x04,
+		.offset = offsetof(struct sns_smgr_buffering_req, item_len),
+	},
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len = SNS_SMGR_DATA_TYPE_COUNT,
+		.elem_size = sizeof(struct sns_smgr_buffering_req_item),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x04,
+		.offset = offsetof(struct sns_smgr_buffering_req, items),
+		.ei_array = sns_smgr_buffering_req_item_ei,
+	},
+	{
+		.data_type = QMI_OPT_FLAG,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req,
+					  notify_suspend_valid),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x10,
+		.offset = offsetof(struct sns_smgr_buffering_req,
+				   notify_suspend_valid),
+	},
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_req,
+					  notify_suspend),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x10,
+		.offset =
+			offsetof(struct sns_smgr_buffering_req, notify_suspend),
+		.ei_array = sns_smgr_buffering_req_notify_suspend_ei,
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+EXPORT_SYMBOL_GPL(sns_smgr_buffering_req_ei);
+
+const struct qmi_elem_info sns_smgr_buffering_resp_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_buffering_resp, result),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x02,
+		.offset = offsetof(struct sns_smgr_buffering_resp, result),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_buffering_resp, report_id),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x10,
+		.offset = offsetof(struct sns_smgr_buffering_resp, report_id),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_buffering_resp, ack_nak),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x11,
+		.offset = offsetof(struct sns_smgr_buffering_resp, ack_nak),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+EXPORT_SYMBOL_GPL(sns_smgr_buffering_resp_ei);
+
+static const struct qmi_elem_info sns_smgr_buffering_report_metadata_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_report_metadata, val1),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_report_metadata,
+				   val1),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size =
+			sizeof_field(struct sns_smgr_buffering_report_metadata,
+				     sample_count),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_report_metadata,
+				   sample_count),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_report_metadata, timestamp),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_report_metadata,
+				   timestamp),
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_report_metadata, val2),
+		.array_type = NO_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_report_metadata,
+				   val2),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+
+static const struct qmi_elem_info sns_smgr_buffering_report_sample_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len = 3,
+		.elem_size = sizeof(u32),
+		.array_type = STATIC_ARRAY,
+		.offset = offsetof(struct sns_smgr_buffering_report_sample,
+				   values),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_report_sample, val1),
+		.array_type = NO_ARRAY,
+		.offset =
+			offsetof(struct sns_smgr_buffering_report_sample, val1),
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_report_sample, val2),
+		.array_type = NO_ARRAY,
+		.offset =
+			offsetof(struct sns_smgr_buffering_report_sample, val2),
+	},
+	{
+		.data_type = QMI_UNSIGNED_2_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(
+			struct sns_smgr_buffering_report_sample, val3),
+		.array_type = NO_ARRAY,
+		.offset =
+			offsetof(struct sns_smgr_buffering_report_sample, val3),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+
+const struct qmi_elem_info sns_smgr_buffering_report_ind_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_report_ind,
+					  report_id),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x01,
+		.offset = offsetof(struct sns_smgr_buffering_report_ind,
+				   report_id),
+	},
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_report_ind,
+					  metadata),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x02,
+		.offset = offsetof(struct sns_smgr_buffering_report_ind,
+				   metadata),
+		.ei_array = sns_smgr_buffering_report_metadata_ei,
+	},
+	{
+		.data_type = QMI_DATA_LEN,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_report_ind,
+					  samples_len),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x03,
+		.offset = offsetof(struct sns_smgr_buffering_report_ind,
+				   samples_len),
+	},
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len = SNS_SMGR_SAMPLES_MAX_LEN,
+		.elem_size = sizeof(struct sns_smgr_buffering_report_sample),
+		.array_type = VAR_LEN_ARRAY,
+		.tlv_type = 0x03,
+		.offset =
+			offsetof(struct sns_smgr_buffering_report_ind, samples),
+		.ei_array = sns_smgr_buffering_report_sample_ei,
+	},
+	{
+		.data_type = QMI_UNSIGNED_1_BYTE,
+		.elem_len = 1,
+		.elem_size = sizeof_field(struct sns_smgr_buffering_report_ind,
+					  val2),
+		.array_type = NO_ARRAY,
+		.tlv_type = 0x10,
+		.offset = offsetof(struct sns_smgr_buffering_report_ind, val2),
+	},
+	{
+		.data_type = QMI_EOTI,
+	},
+};
+EXPORT_SYMBOL_GPL(sns_smgr_buffering_report_ind_ei);
+
+static const char *smgr_sensor_type_names[SNS_SMGR_SENSOR_TYPE_COUNT] = {
+	[SNS_SMGR_SENSOR_TYPE_ACCEL] = "ACCEL",
+	[SNS_SMGR_SENSOR_TYPE_GYRO] = "GYRO",
+	[SNS_SMGR_SENSOR_TYPE_MAG] = "MAG",
+	[SNS_SMGR_SENSOR_TYPE_PROX_LIGHT] = "PROX_LIGHT",
+	[SNS_SMGR_SENSOR_TYPE_PRESSURE] = "PRESSURE",
+	[SNS_SMGR_SENSOR_TYPE_HALL_EFFECT] = "HALL_EFFECT"
+};
+
+enum qcom_smgr_sensor_type sns_smgr_sensor_type_from_str(const char *str)
+{
+	enum qcom_smgr_sensor_type i;
+
+	for (i = SNS_SMGR_SENSOR_TYPE_UNKNOWN + 1;
+	     i < SNS_SMGR_SENSOR_TYPE_COUNT; i++)
+		if (!strcmp(str, smgr_sensor_type_names[i]))
+			return i;
+
+	return SNS_SMGR_SENSOR_TYPE_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(sns_smgr_sensor_type_from_str);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/common/qcom_smgr/qmi/sns_smgr.h b/drivers/iio/common/qcom_smgr/qmi/sns_smgr.h
new file mode 100644
index 000000000000..a741dfd87452
--- /dev/null
+++ b/drivers/iio/common/qcom_smgr/qmi/sns_smgr.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SSC_SNS_SMGR_H__
+#define __SSC_SNS_SMGR_H__
+
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/soc/qcom/qmi.h>
+#include <linux/types.h>
+
+/*
+ * The structures of QMI messages used by the service were determined
+ * purely by watching transactions between proprietary Android userspace
+ * components and SSC. along with comparing values reported by Android APIs
+ * to values received in response messages. Due to that, the purpose or
+ * meaning of many fields remains unknown. Such fields are named "val*",
+ * "data*" or similar. Furthermore, the true maximum sizes of some messages
+ * with unknown array fields may be different than defined here.
+ */
+
+#define SNS_SMGR_QMI_SVC_ID			0x0100
+#define SNS_SMGR_QMI_SVC_V1			1
+#define SNS_SMGR_QMI_INS_ID			50
+
+#define SNS_SMGR_ALL_SENSOR_INFO_MSG_ID		0x05
+#define SNS_SMGR_SINGLE_SENSOR_INFO_MSG_ID	0x06
+#define SNS_SMGR_BUFFERING_MSG_ID		0x21
+#define SNS_SMGR_BUFFERING_REPORT_MSG_ID	0x22
+
+#define SNS_SMGR_ALL_SENSOR_INFO_REQ_MAX_LEN		0x0
+#define SNS_SMGR_ALL_SENSOR_INFO_RESP_MAX_LEN		0x3e
+#define SNS_SMGR_SINGLE_SENSOR_INFO_REQ_MAX_LEN		0x4
+#define SNS_SMGR_SINGLE_SENSOR_INFO_RESP_MAX_LEN	0x110
+#define SNS_SMGR_BUFFERING_REQ_MAX_LEN			0x30
+#define SNS_SMGR_BUFFERING_RESP_MAX_LEN			0x1e
+
+/* TODO: find actual maximums */
+#define SNS_SMGR_ALL_SENSOR_INFO_MAX_LEN	0x10
+#define SNS_SMGR_SENSOR_TYPE_MAX_LEN		0x10
+#define SNS_SMGR_NATIVE_SAMPLE_RATES_MAX_LEN	0x20
+#define SNS_SMGR_SAMPLES_MAX_LEN		0x100
+
+enum sns_smgr_buffering_action {
+	SNS_SMGR_BUFFERING_ACTION_ADD	 = 1,
+	SNS_SMGR_BUFFERING_ACTION_DELETE = 2,
+};
+
+struct sns_smgr_all_sensor_info {
+	u8 id;
+	u8 type_len;
+	char type[SNS_SMGR_SENSOR_TYPE_MAX_LEN];
+};
+
+struct sns_smgr_all_sensor_info_resp {
+	u16 result;
+	u8 item_len;
+	struct sns_smgr_all_sensor_info items[SNS_SMGR_ALL_SENSOR_INFO_MAX_LEN];
+};
+
+struct sns_smgr_single_sensor_info_req {
+	u8 sensor_id;
+};
+
+struct sns_smgr_single_sensor_info_data_type {
+	u8 sensor_id;
+	u8 data_type;
+	u8 name_len;
+	char name[0xff];
+	u8 vendor_len;
+	char vendor[0xff];
+	/*
+	 * Might be separate u8 or u16 fields, but taken as a u32 it is seen
+	 * to hold the value 1 for all sensors in dumps.
+	 */
+	u32 val1;
+	u16 max_sample_rate_hz;
+	u16 val2;
+	u16 current_ua;
+	u32 range;
+	u32 resolution;
+};
+
+struct sns_smgr_single_sensor_info_native_sample_rates {
+	u8 rate_count;
+	u16 rates[SNS_SMGR_NATIVE_SAMPLE_RATES_MAX_LEN];
+};
+
+struct sns_smgr_single_sensor_info_resp {
+	u16 result;
+	u8 data_type_len;
+	struct sns_smgr_single_sensor_info_data_type data_types[SNS_SMGR_DATA_TYPE_COUNT];
+	u8 data1_len;
+	u32 data1[SNS_SMGR_DATA_TYPE_COUNT];
+	u32 data2;
+	u8 data3_len;
+	u64 data3[SNS_SMGR_DATA_TYPE_COUNT];
+	u8 native_sample_rates_len;
+	struct sns_smgr_single_sensor_info_native_sample_rates
+		native_sample_rates[SNS_SMGR_DATA_TYPE_COUNT];
+	u8 data5_len;
+	u32 data5[SNS_SMGR_DATA_TYPE_COUNT];
+};
+
+struct sns_smgr_buffering_req_item {
+	u8 sensor_id;
+	u8 data_type;
+	u16 val1;
+	u16 sampling_rate;
+	u16 val2;
+};
+
+struct sns_smgr_buffering_req_notify_suspend {
+	u16 proc_type;
+	u16 send_indications_during_suspend;
+};
+
+struct sns_smgr_buffering_req {
+	u8 report_id;
+	u8 action;
+	u32 report_rate;
+	u8 item_len;
+	struct sns_smgr_buffering_req_item items[SNS_SMGR_DATA_TYPE_COUNT];
+	u8 notify_suspend_valid;
+	struct sns_smgr_buffering_req_notify_suspend notify_suspend;
+};
+
+struct sns_smgr_buffering_resp {
+	u16 result;
+	u8 report_id;
+	u8 ack_nak;
+};
+
+struct sns_smgr_buffering_report_metadata {
+	u32 val1;
+	u8 sample_count;
+	u32 timestamp;
+	u32 val2;
+};
+
+struct sns_smgr_buffering_report_sample {
+	u32 values[3];
+	u8 val1;
+	u8 val2;
+	u16 val3;
+};
+
+struct sns_smgr_buffering_report_ind {
+	u8 report_id;
+	struct sns_smgr_buffering_report_metadata metadata;
+	u8 samples_len;
+	struct sns_smgr_buffering_report_sample samples[SNS_SMGR_SAMPLES_MAX_LEN];
+	u8 val2;
+};
+
+extern const struct qmi_elem_info sns_smgr_all_sensor_info_resp_ei[];
+extern const struct qmi_elem_info sns_smgr_single_sensor_info_req_ei[];
+extern const struct qmi_elem_info sns_smgr_single_sensor_info_resp_ei[];
+extern const struct qmi_elem_info sns_smgr_buffering_req_ei[];
+extern const struct qmi_elem_info sns_smgr_buffering_resp_ei[];
+extern const struct qmi_elem_info sns_smgr_buffering_report_ind_ei[];
+
+extern enum qcom_smgr_sensor_type sns_smgr_sensor_type_from_str(const char *str);
+
+#endif /* __SSC_SNS_SMGR_H__ */
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 3e193ee0fb61..b9ee2c3b5bc5 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -147,6 +147,16 @@ config IIO_ST_GYRO_3AXIS
 	  Also need to enable at least one of I2C and SPI interface drivers
 	  below.
 
+config IIO_QCOM_SMGR_GYRO
+	tristate "Qualcomm SSC Sensor Manager Gyroscope Sensor"
+	depends on IIO_QCOM_SMGR
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say yes here to get support for gyroscopes connected to
+	  a Qualcomm Snapdragon Sensor Core and accessed through its
+	  Sensor Manager service.
+
 config IIO_ST_GYRO_I2C_3AXIS
 	tristate "STMicroelectronics gyroscopes 3-Axis I2C Interface"
 	depends on I2C && IIO_ST_GYRO_3AXIS
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index 0319b397dc3f..63ff40acdedc 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -28,6 +28,8 @@ itg3200-y               := itg3200_core.o
 itg3200-$(CONFIG_IIO_BUFFER) += itg3200_buffer.o
 obj-$(CONFIG_ITG3200)   += itg3200.o
 
+obj-$(CONFIG_IIO_QCOM_SMGR_ACCEL) += qcom_smgr_gyro.o
+
 obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_gyro_sensor.o
 
 obj-$(CONFIG_IIO_ST_GYRO_3AXIS) += st_gyro.o
diff --git a/drivers/iio/gyro/qcom_smgr_gyro.c b/drivers/iio/gyro/qcom_smgr_gyro.c
new file mode 100644
index 000000000000..4cb55c6fe9e8
--- /dev/null
+++ b/drivers/iio/gyro/qcom_smgr_gyro.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Sensor Manager gyroscope driver
+ *
+ * Copyright (c) 2022, Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+
+static const struct iio_chan_spec qcom_smgr_gyro_iio_channels[] = {
+	{
+		.type = IIO_ANGL_VEL,
+		.modified = true,
+		.channel2 = IIO_MOD_X,
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_ANGL_VEL,
+		.modified = true,
+		.channel2 = IIO_MOD_Y,
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_ANGL_VEL,
+		.modified = true,
+		.channel2 = IIO_MOD_Z,
+		.scan_index = 2,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_TIMESTAMP,
+		.channel = -1,
+		.scan_index = 3,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 32,
+			.storagebits = 64,
+			.endianness = IIO_LE,
+		},
+	},
+};
+
+static int qcom_smgr_gyro_probe(struct platform_device *pdev)
+{
+	struct iio_dev *iio_dev;
+	struct qcom_smgr_iio_priv *priv;
+	int ret;
+
+	iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	priv = iio_priv(iio_dev);
+	priv->sensor = *(struct qcom_smgr_sensor **)pdev->dev.platform_data;
+	priv->sensor->iio_dev = iio_dev;
+
+	iio_dev->name = "qcom-smgr-gyro";
+	iio_dev->info = &qcom_smgr_iio_info;
+	iio_dev->channels = qcom_smgr_gyro_iio_channels;
+	iio_dev->num_channels = ARRAY_SIZE(qcom_smgr_gyro_iio_channels);
+
+	ret = devm_iio_kfifo_buffer_setup(&pdev->dev, iio_dev,
+					  &qcom_smgr_buffer_ops);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to setup buffer: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	ret = devm_iio_device_register(&pdev->dev, iio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register IIO device: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv->sensor);
+
+	return 0;
+}
+
+static void qcom_smgr_gyro_remove(struct platform_device *pdev)
+{
+	struct qcom_smgr_sensor *sensor = platform_get_drvdata(pdev);
+
+	sensor->iio_dev = NULL;
+}
+
+static const struct platform_device_id qcom_smgr_gyro_ids[] = {
+	{ .name = "qcom-smgr-gyro" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, qcom_smgr_gyro_ids);
+
+static struct platform_driver qcom_smgr_gyro_driver = {
+	.probe = qcom_smgr_gyro_probe,
+	.remove = qcom_smgr_gyro_remove,
+	.driver	= {
+		.name = "qcom_smgr_gyro",
+	},
+	.id_table = qcom_smgr_gyro_ids,
+};
+module_platform_driver(qcom_smgr_gyro_driver);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm Sensor Manager gyroscope driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index 3debf1320ad1..917c123f08bb 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -139,6 +139,15 @@ config MMC35240
 	  To compile this driver as a module, choose M here: the module
 	  will be called mmc35240.
 
+config IIO_QCOM_SMGR_MAG
+	tristate "Qualcomm SSC Sensor Manager Magnetometer"
+	depends on IIO_QCOM_SMGR
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say yes here to get support for magnetometers connected to a Qualcomm
+	  Snapdragon Sensor Core and accessed through its Sensor Manager service.
+
 config IIO_ST_MAGN_3AXIS
 	tristate "STMicroelectronics magnetometers 3-Axis Driver"
 	depends on (I2C || SPI_MASTER) && SYSFS
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index 9297723a97d8..7576c226239b 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_MAG3110)	+= mag3110.o
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
 obj-$(CONFIG_MMC35240)	+= mmc35240.o
 
+obj-$(CONFIG_IIO_QCOM_SMGR_MAG) += qcom_smgr_mag.o
+
 obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o
 st_magn-y := st_magn_core.o
 st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o
diff --git a/drivers/iio/magnetometer/qcom_smgr_mag.c b/drivers/iio/magnetometer/qcom_smgr_mag.c
new file mode 100644
index 000000000000..dc197db509bc
--- /dev/null
+++ b/drivers/iio/magnetometer/qcom_smgr_mag.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Sensor Manager magnetometer driver
+ *
+ * Copyright (c) 2022, Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+
+static const struct iio_chan_spec qcom_smgr_mag_iio_channels[] = {
+	{
+		.type = IIO_MAGN,
+		.modified = true,
+		.channel2 = IIO_MOD_X,
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_MAGN,
+		.modified = true,
+		.channel2 = IIO_MOD_Y,
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_MAGN,
+		.modified = true,
+		.channel2 = IIO_MOD_Z,
+		.scan_index = 2,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.ext_info = qcom_smgr_iio_ext_info
+	},
+	{
+		.type = IIO_TIMESTAMP,
+		.channel = -1,
+		.scan_index = 3,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 32,
+			.storagebits = 64,
+			.endianness = IIO_LE,
+		},
+	},
+};
+
+static int qcom_smgr_mag_probe(struct platform_device *pdev)
+{
+	struct iio_dev *iio_dev;
+	struct qcom_smgr_iio_priv *priv;
+	int ret;
+
+	iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	priv = iio_priv(iio_dev);
+	priv->sensor = *(struct qcom_smgr_sensor **)pdev->dev.platform_data;
+	priv->sensor->iio_dev = iio_dev;
+
+	iio_dev->name = "qcom-smgr-mag";
+	iio_dev->info = &qcom_smgr_iio_info;
+	iio_dev->channels = qcom_smgr_mag_iio_channels;
+	iio_dev->num_channels = ARRAY_SIZE(qcom_smgr_mag_iio_channels);
+
+	ret = devm_iio_kfifo_buffer_setup(&pdev->dev, iio_dev,
+					  &qcom_smgr_buffer_ops);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to setup buffer: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	ret = devm_iio_device_register(&pdev->dev, iio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register IIO device: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv->sensor);
+
+	return 0;
+}
+
+static void qcom_smgr_mag_remove(struct platform_device *pdev)
+{
+	struct qcom_smgr_sensor *sensor = platform_get_drvdata(pdev);
+
+	sensor->iio_dev = NULL;
+}
+
+static const struct platform_device_id qcom_smgr_mag_ids[] = {
+	{ .name = "qcom-smgr-mag" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, qcom_smgr_mag_ids);
+
+static struct platform_driver qcom_smgr_mag_driver = {
+	.probe = qcom_smgr_mag_probe,
+	.remove = qcom_smgr_mag_remove,
+	.driver	= {
+		.name = "qcom_smgr_mag",
+	},
+	.id_table = qcom_smgr_mag_ids,
+};
+module_platform_driver(qcom_smgr_mag_driver);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm Sensor Manager magnetometer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index d2cb8c871f6a..ca1053472969 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -67,6 +67,16 @@ config IIO_CROS_EC_BARO
 	  To compile this driver as a module, choose M here: the module
 	  will be called cros_ec_baro.
 
+config IIO_QCOM_SMGR_PRESSURE
+	tristate "Qualcomm SSC Sensor Manager Pressure Sensor"
+	depends on IIO_QCOM_SMGR
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say yes here to get support for pressure sensors connected to
+	  a Qualcomm Snapdragon Sensor Core and accessed through its Sensor
+	  Manager service.
+
 config DLHL60D
 	tristate "All Sensors DLHL60D and DLHL60G low voltage digital pressure sensors"
 	depends on I2C
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
index 6482288e07ee..0e4a1fbef7b8 100644
--- a/drivers/iio/pressure/Makefile
+++ b/drivers/iio/pressure/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_BMP280_SPI) += bmp280-spi.o
 obj-$(CONFIG_DLHL60D) += dlhl60d.o
 obj-$(CONFIG_DPS310) += dps310.o
 obj-$(CONFIG_IIO_CROS_EC_BARO) += cros_ec_baro.o
+obj-$(CONFIG_IIO_QCOM_SMGR_PROX) += qcom_smgr_pressure.o
 obj-$(CONFIG_HID_SENSOR_PRESS)   += hid-sensor-press.o
 obj-$(CONFIG_HP03) += hp03.o
 obj-$(CONFIG_HSC030PA) += hsc030pa.o
diff --git a/drivers/iio/pressure/qcom_smgr_pressure.c b/drivers/iio/pressure/qcom_smgr_pressure.c
new file mode 100644
index 000000000000..66e165ad5c9a
--- /dev/null
+++ b/drivers/iio/pressure/qcom_smgr_pressure.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Sensor Manager pressure sensor driver
+ *
+ * Copyright (c) 2022, Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+
+static const struct iio_chan_spec qcom_smgr_pressure_iio_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_separate = BIT(IIO_CHAN_INFO_OFFSET) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_SAMP_FREQ)
+	},
+	{
+		.type = IIO_TIMESTAMP,
+		.channel = -1,
+		.scan_index = 3,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 32,
+			.storagebits = 64,
+			.endianness = IIO_LE,
+		},
+	},
+};
+
+static int qcom_smgr_pressure_probe(struct platform_device *pdev)
+{
+	struct iio_dev *iio_dev;
+	struct qcom_smgr_iio_priv *priv;
+	int ret;
+
+	iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	priv = iio_priv(iio_dev);
+	priv->sensor = *(struct qcom_smgr_sensor **)pdev->dev.platform_data;
+	priv->sensor->iio_dev = iio_dev;
+
+	iio_dev->name = "qcom-smgr-pressure";
+	iio_dev->info = &qcom_smgr_iio_info;
+	iio_dev->channels = qcom_smgr_pressure_iio_channels;
+	iio_dev->num_channels = ARRAY_SIZE(qcom_smgr_pressure_iio_channels);
+
+	ret = devm_iio_kfifo_buffer_setup(&pdev->dev, iio_dev,
+					  &qcom_smgr_buffer_ops);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to setup buffer: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	ret = devm_iio_device_register(&pdev->dev, iio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register IIO device: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv->sensor);
+
+	return 0;
+}
+
+static void qcom_smgr_pressure_remove(struct platform_device *pdev)
+{
+	struct qcom_smgr_sensor *sensor = platform_get_drvdata(pdev);
+
+	sensor->iio_dev = NULL;
+}
+
+static const struct platform_device_id qcom_smgr_pressure_ids[] = {
+	{ .name = "qcom-smgr-pressure" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, qcom_smgr_pressure_ids);
+
+static struct platform_driver qcom_smgr_pressure_driver = {
+	.probe = qcom_smgr_pressure_probe,
+	.remove = qcom_smgr_pressure_remove,
+	.driver	= {
+		.name = "qcom_smgr_pressure",
+	},
+	.id_table = qcom_smgr_pressure_ids,
+};
+module_platform_driver(qcom_smgr_pressure_driver);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm Sensor Manager pressure sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index a562a78b7d0d..486514e54cc1 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -46,6 +46,16 @@ config HX9023S
 	  To compile this driver as a module, choose M here: the
 	  module will be called hx9023s.
 
+config IIO_QCOM_SMGR_PROX
+	tristate "Qualcomm SSC Sensor Manager Proximity Sensor"
+	depends on IIO_QCOM_SMGR
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say yes here to get support for proximity sensors connected to
+	  a Qualcomm Snapdragon Sensor Core and accessed through its Sensor
+	  Manager service.
+
 config IRSD200
 	tristate "Murata IRS-D200 PIR sensor"
 	select IIO_BUFFER
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index c5e76995764a..c3dab31e1fc1 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_AS3935)		+= as3935.o
 obj-$(CONFIG_CROS_EC_MKBP_PROXIMITY) += cros_ec_mkbp_proximity.o
 obj-$(CONFIG_HX9023S)		+= hx9023s.o
+obj-$(CONFIG_IIO_QCOM_SMGR_PROX) += qcom_smgr_prox.o
 obj-$(CONFIG_IRSD200)		+= irsd200.o
 obj-$(CONFIG_ISL29501)		+= isl29501.o
 obj-$(CONFIG_LIDAR_LITE_V2)	+= pulsedlight-lidar-lite-v2.o
diff --git a/drivers/iio/proximity/qcom_smgr_prox.c b/drivers/iio/proximity/qcom_smgr_prox.c
new file mode 100644
index 000000000000..2900fb7b7a20
--- /dev/null
+++ b/drivers/iio/proximity/qcom_smgr_prox.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Sensor Manager proximity sensor driver
+ *
+ * Copyright (c) 2022, Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/common/qcom_smgr.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+
+static const struct iio_chan_spec qcom_smgr_prox_iio_channels[] = {
+	{
+		.type = IIO_PROXIMITY,
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.info_mask_separate = BIT(IIO_CHAN_INFO_OFFSET) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_SAMP_FREQ)
+	},
+	{
+		.type = IIO_TIMESTAMP,
+		.channel = -1,
+		.scan_index = 3,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 32,
+			.storagebits = 64,
+			.endianness = IIO_LE,
+		},
+	},
+};
+
+static int qcom_smgr_prox_probe(struct platform_device *pdev)
+{
+	struct iio_dev *iio_dev;
+	struct qcom_smgr_iio_priv *priv;
+	int ret;
+
+	iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	priv = iio_priv(iio_dev);
+	priv->sensor = *(struct qcom_smgr_sensor **)pdev->dev.platform_data;
+	priv->sensor->iio_dev = iio_dev;
+
+	iio_dev->name = "qcom-smgr-prox";
+	iio_dev->info = &qcom_smgr_iio_info;
+	iio_dev->channels = qcom_smgr_prox_iio_channels;
+	iio_dev->num_channels = ARRAY_SIZE(qcom_smgr_prox_iio_channels);
+
+	ret = devm_iio_kfifo_buffer_setup(&pdev->dev, iio_dev,
+					  &qcom_smgr_buffer_ops);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to setup buffer: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	ret = devm_iio_device_register(&pdev->dev, iio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register IIO device: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv->sensor);
+
+	return 0;
+}
+
+static void qcom_smgr_prox_remove(struct platform_device *pdev)
+{
+	struct qcom_smgr_sensor *sensor = platform_get_drvdata(pdev);
+
+	sensor->iio_dev = NULL;
+}
+
+static const struct platform_device_id qcom_smgr_prox_ids[] = {
+	{ .name = "qcom-smgr-prox-light" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, qcom_smgr_prox_ids);
+
+static struct platform_driver qcom_smgr_prox_driver = {
+	.probe = qcom_smgr_prox_probe,
+	.remove = qcom_smgr_prox_remove,
+	.driver	= {
+		.name = "qcom_smgr_prox",
+	},
+	.id_table = qcom_smgr_prox_ids,
+};
+module_platform_driver(qcom_smgr_prox_driver);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm Sensor Manager proximity sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/iio/common/qcom_smgr.h b/include/linux/iio/common/qcom_smgr.h
new file mode 100644
index 000000000000..756cb83e26ec
--- /dev/null
+++ b/include/linux/iio/common/qcom_smgr.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __QCOM_SMGR_H__
+#define __QCOM_SMGR_H__
+
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+#include <linux/types.h>
+
+enum qcom_smgr_sensor_type {
+	SNS_SMGR_SENSOR_TYPE_UNKNOWN,
+	SNS_SMGR_SENSOR_TYPE_ACCEL,
+	SNS_SMGR_SENSOR_TYPE_GYRO,
+	SNS_SMGR_SENSOR_TYPE_MAG,
+	SNS_SMGR_SENSOR_TYPE_PROX_LIGHT,
+	SNS_SMGR_SENSOR_TYPE_PRESSURE,
+	SNS_SMGR_SENSOR_TYPE_HALL_EFFECT,
+
+	SNS_SMGR_SENSOR_TYPE_COUNT
+};
+
+enum qcom_smgr_data_type {
+	SNS_SMGR_DATA_TYPE_PRIMARY,
+	SNS_SMGR_DATA_TYPE_SECONDARY,
+
+	SNS_SMGR_DATA_TYPE_COUNT
+};
+
+struct qcom_smgr_data_type_item {
+	const char *name;
+	const char *vendor;
+
+	u32 range;
+
+	size_t native_sample_rate_count;
+	u16 *native_sample_rates;
+
+	u16 max_sample_rate;
+	u16 cur_sample_rate;
+};
+
+struct qcom_smgr_sensor {
+	u8 id;
+	enum qcom_smgr_sensor_type type;
+
+	u8 data_type_count;
+	/*
+	 * Only SNS_SMGR_DATA_TYPE_PRIMARY is used at the moment, but we store
+	 * SNS_SMGR_DATA_TYPE_SECONDARY when available as well for future use.
+	 */
+	struct qcom_smgr_data_type_item *data_types;
+
+	struct iio_dev *iio_dev;
+};
+
+struct qcom_smgr_iio_priv {
+	struct qcom_smgr_sensor *sensor;
+};
+
+extern const struct iio_buffer_setup_ops qcom_smgr_buffer_ops;
+extern const struct iio_info qcom_smgr_iio_info;
+extern const struct iio_chan_spec_ext_info qcom_smgr_iio_ext_info[];
+
+#endif /* __QCOM_SMGR_H__ */
