#include <linux/debugfs.h>
 #include <linux/mutex.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/iio-opaque.h>
 #include "iio_core.h"
 #include "iio_core_trigger.h"
 #include <linux/iio/sysfs.h>
 static void iio_dev_release(struct device *device)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(device);
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+
        if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
                iio_device_unregister_trigger_consumer(indio_dev);
        iio_device_unregister_eventset(indio_dev);
        iio_buffer_put(indio_dev->buffer);
 
        ida_simple_remove(&iio_ida, indio_dev->id);
-       kfree(indio_dev);
+       kfree(iio_dev_opaque);
 }
 
 struct device_type iio_device_type = {
  **/
 struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
 {
+       struct iio_dev_opaque *iio_dev_opaque;
        struct iio_dev *dev;
        size_t alloc_size;
 
-       alloc_size = sizeof(struct iio_dev);
+       alloc_size = sizeof(struct iio_dev_opaque);
        if (sizeof_priv) {
                alloc_size = ALIGN(alloc_size, IIO_ALIGN);
                alloc_size += sizeof_priv;
        /* ensure 32-byte alignment of whole construct ? */
        alloc_size += IIO_ALIGN - 1;
 
-       dev = kzalloc(alloc_size, GFP_KERNEL);
-       if (!dev)
+       iio_dev_opaque = kzalloc(alloc_size, GFP_KERNEL);
+       if (!iio_dev_opaque)
                return NULL;
 
-       dev->dev.parent = parent;
+       dev = &iio_dev_opaque->indio_dev;
+       dev->priv = (char *)iio_dev_opaque +
+               ALIGN(sizeof(struct iio_dev_opaque), IIO_ALIGN);
+
        dev->dev.groups = dev->groups;
        dev->dev.type = &iio_device_type;
        dev->dev.bus = &iio_bus_type;
        if (dev->id < 0) {
                /* cannot use a dev_err as the name isn't available */
                pr_err("failed to get device id\n");
-               kfree(dev);
+               kfree(iio_dev_opaque);
                return NULL;
        }
        dev_set_name(&dev->dev, "iio:device%d", dev->id);
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _INDUSTRIAL_IO_OPAQUE_H_
+#define _INDUSTRIAL_IO_OPAQUE_H_
+
+/**
+ * struct iio_dev_opaque - industrial I/O device opaque information
+ * @indio_dev:                 public industrial I/O device information
+ */
+struct iio_dev_opaque {
+       struct iio_dev                  indio_dev;
+};
+
+#define to_iio_dev_opaque(indio_dev)           \
+       container_of(indio_dev, struct iio_dev_opaque, indio_dev)
+
+#endif
 
  * @flags:             [INTERN] file ops related flags including busy flag.
  * @debugfs_dentry:    [INTERN] device specific debugfs dentry.
  * @cached_reg_addr:   [INTERN] cached register address for debugfs reads.
+ * @priv:              [DRIVER] reference to driver's private information
+ *                     **MUST** be accessed **ONLY** via iio_priv() helper
  */
 struct iio_dev {
        int                             id;
        char                            read_buf[20];
        unsigned int                    read_buf_len;
 #endif
+       void                            *priv;
 };
 
 const struct iio_chan_spec
 #define IIO_ALIGN L1_CACHE_BYTES
 struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv);
 
+/* The information at the returned address is guaranteed to be cacheline aligned */
 static inline void *iio_priv(const struct iio_dev *indio_dev)
 {
-       return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN);
+       return indio_dev->priv;
 }
 
 static inline struct iio_dev *iio_priv_to_dev(void *priv)