#define MS5611_RESET                   0x1e
 #define MS5611_READ_ADC                        0x00
 #define MS5611_READ_PROM_WORD          0xA0
-#define MS5611_START_TEMP_CONV         0x58
-#define MS5611_START_PRESSURE_CONV     0x48
-
-#define MS5611_CONV_TIME_MIN           9040
-#define MS5611_CONV_TIME_MAX           10000
-
 #define MS5611_PROM_WORDS_NB           8
 
 enum {
                                            s32 *temp, s32 *pressure);
 };
 
+/*
+ * OverSampling Rate descriptor.
+ * Warning: cmd MUST be kept aligned on a word boundary (see
+ * m5611_spi_read_adc_temp_and_pressure in ms5611_spi.c).
+ */
+struct ms5611_osr {
+       unsigned long conv_usec;
+       u8 cmd;
+       unsigned short rate;
+};
+
 struct ms5611_state {
        void *client;
        struct mutex lock;
 
+       const struct ms5611_osr *pressure_osr;
+       const struct ms5611_osr *temp_osr;
+
        int (*reset)(struct device *dev);
        int (*read_prom_word)(struct device *dev, int index, u16 *word);
        int (*read_adc_temp_and_pressure)(struct device *dev,
 
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 
+#include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/trigger_consumer.h>
 #include "ms5611.h"
 
+#define MS5611_INIT_OSR(_cmd, _conv_usec, _rate) \
+       { .cmd = _cmd, .conv_usec = _conv_usec, .rate = _rate }
+
+static const struct ms5611_osr ms5611_avail_pressure_osr[] = {
+       MS5611_INIT_OSR(0x40, 600,  256),
+       MS5611_INIT_OSR(0x42, 1170, 512),
+       MS5611_INIT_OSR(0x44, 2280, 1024),
+       MS5611_INIT_OSR(0x46, 4540, 2048),
+       MS5611_INIT_OSR(0x48, 9040, 4096)
+};
+
+static const struct ms5611_osr ms5611_avail_temp_osr[] = {
+       MS5611_INIT_OSR(0x50, 600,  256),
+       MS5611_INIT_OSR(0x52, 1170, 512),
+       MS5611_INIT_OSR(0x54, 2280, 1024),
+       MS5611_INIT_OSR(0x56, 4540, 2048),
+       MS5611_INIT_OSR(0x58, 9040, 4096)
+};
+
+static const char ms5611_show_osr[] = "256 512 1024 2048 4096";
+
+static IIO_CONST_ATTR(oversampling_ratio_available, ms5611_show_osr);
+
+static struct attribute *ms5611_attributes[] = {
+       &iio_const_attr_oversampling_ratio_available.dev_attr.attr,
+       NULL,
+};
+
+static const struct attribute_group ms5611_attribute_group = {
+       .attrs = ms5611_attributes,
+};
+
 static bool ms5611_prom_is_valid(u16 *prom, size_t len)
 {
        int i, j;
                default:
                        return -EINVAL;
                }
+       case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+               if (chan->type != IIO_TEMP && chan->type != IIO_PRESSURE)
+                       break;
+               mutex_lock(&st->lock);
+               if (chan->type == IIO_TEMP)
+                       *val = (int)st->temp_osr->rate;
+               else
+                       *val = (int)st->pressure_osr->rate;
+               mutex_unlock(&st->lock);
+               return IIO_VAL_INT;
        }
 
        return -EINVAL;
 }
 
+static const struct ms5611_osr *ms5611_find_osr(int rate,
+                                               const struct ms5611_osr *osr,
+                                               size_t count)
+{
+       unsigned int r;
+
+       for (r = 0; r < count; r++)
+               if ((unsigned short)rate == osr[r].rate)
+                       break;
+       if (r >= count)
+               return NULL;
+       return &osr[r];
+}
+
+static int ms5611_write_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int val, int val2, long mask)
+{
+       struct ms5611_state *st = iio_priv(indio_dev);
+       const struct ms5611_osr *osr = NULL;
+
+       if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
+               return -EINVAL;
+
+       if (chan->type == IIO_TEMP)
+               osr = ms5611_find_osr(val, ms5611_avail_temp_osr,
+                                     ARRAY_SIZE(ms5611_avail_temp_osr));
+       else if (chan->type == IIO_PRESSURE)
+               osr = ms5611_find_osr(val, ms5611_avail_pressure_osr,
+                                     ARRAY_SIZE(ms5611_avail_pressure_osr));
+       if (!osr)
+               return -EINVAL;
+
+       mutex_lock(&st->lock);
+
+       if (iio_buffer_enabled(indio_dev)) {
+               mutex_unlock(&st->lock);
+               return -EBUSY;
+       }
+
+       if (chan->type == IIO_TEMP)
+               st->temp_osr = osr;
+       else
+               st->pressure_osr = osr;
+
+       mutex_unlock(&st->lock);
+       return 0;
+}
+
 static const unsigned long ms5611_scan_masks[] = {0x3, 0};
 
 static struct ms5611_chip_info chip_info_tbl[] = {
        {
                .type = IIO_PRESSURE,
                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-                       BIT(IIO_CHAN_INFO_SCALE),
+                       BIT(IIO_CHAN_INFO_SCALE) |
+                       BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
                .scan_index = 0,
                .scan_type = {
                        .sign = 's',
        {
                .type = IIO_TEMP,
                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-                       BIT(IIO_CHAN_INFO_SCALE),
+                       BIT(IIO_CHAN_INFO_SCALE) |
+                       BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
                .scan_index = 1,
                .scan_type = {
                        .sign = 's',
 
 static const struct iio_info ms5611_info = {
        .read_raw = &ms5611_read_raw,
+       .write_raw = &ms5611_write_raw,
+       .attrs = &ms5611_attribute_group,
        .driver_module = THIS_MODULE,
 };
 
 
        mutex_init(&st->lock);
        st->chip_info = &chip_info_tbl[type];
+       st->temp_osr =
+               &ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
+       st->pressure_osr =
+               &ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr)
+                                          - 1];
        indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ms5611_info;
 
 static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,
                                                 s32 *temp, s32 *pressure)
 {
-       u8 cmd;
        int ret;
        struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+       const struct ms5611_osr *osr = st->temp_osr;
 
-       cmd = MS5611_START_TEMP_CONV;
-       ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+       /*
+        * Warning: &osr->cmd MUST be aligned on a word boundary since used as
+        * 2nd argument (void*) of spi_write_then_read.
+        */
+       ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
        if (ret < 0)
                return ret;
 
-       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+       usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
        ret = ms5611_spi_read_adc(dev, temp);
        if (ret < 0)
                return ret;
 
-       cmd = MS5611_START_PRESSURE_CONV;
-       ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+       osr = st->pressure_osr;
+       ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
        if (ret < 0)
                return ret;
 
-       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+       usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
        return ms5611_spi_read_adc(dev, pressure);
 }