]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blobdiff - drivers/iio/pressure/nvi_bmpX80.c
iio: imu: nvi v.336 Add DMP AUX support
[sojka/nv-tegra/linux-3.10.git] / drivers / iio / pressure / nvi_bmpX80.c
index 6b61cc8901e32f2d45e1b561cb254bd0f54a8fcc..8bf7f7ed4a250e0938a4c8e32803594ae8ef7cd9 100644 (file)
  * initialize.  No device identification and connect testing is done for
  * specific configurations.
  */
-/* A defined interrupt can be used as a SW flag to configure the device if
- * behind the MPU.  When an interrupt is defined in struct i2c_client.irq,
- * the driver is configured to only use the device's continuous mode if the
- * device supports it.  The interrupt itself is never touched so any value can
- * be used.  This frees the MPU auxiliary port used for writes.  This
- * configuration would be used if another MPU auxiliary port was needed for
- * another device connected to the MPU.  The delay timing used in continuous
- * mode is equal to or the next fastest supported speed.
- */
 /* The NVS = NVidia Sensor framework */
 /* NVI = NVidia/Invensense */
 /* See Nvs.cpp in the HAL for the NVS implementation of batch/flush. */
@@ -60,7 +51,7 @@
 #include <linux/mpu_iio.h>
 #endif /* BMP_NVI_MPU_SUPPORT */
 
-#define BMP_DRIVER_VERSION             (325)
+#define BMP_DRIVER_VERSION             (336)
 #define BMP_VENDOR                     "Bosch"
 #define BMP_NAME                       "bmpX80"
 #define BMP180_NAME                    "bmp180"
@@ -70,9 +61,6 @@
 #define BMP_PRES_MAX_RANGE_MICRO       (0)
 #define BMP_TEMP_MAX_RANGE_IVAL                (125)
 #define BMP_TEMP_MAX_RANGE_MICRO       (0)
-#define BMP180_RANGE_DFLT              (0)
-/* until BMP280 OSS pressure calculation is supported, this defaults to 5 */
-#define BMP280_RANGE_DFLT              (5)
 #define BMP_HW_DELAY_POR_MS            (10)
 #define BMP_POLL_DELAY_MS_DFLT         (200)
 #define BMP_MPU_RETRY_COUNT            (50)
@@ -95,9 +83,7 @@
 #define BMP280_REG_CTRL_MODE_FORCED2   (2)
 #define BMP280_REG_CTRL_MODE_NORMAL    (3)
 #define BMP280_REG_CTRL_OSRS_P         (2)
-#define BMP280_REG_CTRL_OSRS_P_MASK    (0x1C)
 #define BMP280_REG_CTRL_OSRS_T         (5)
-#define BMP280_REG_CTRL_OSRS_T_MASK    (0xE0)
 #define BMP180_REG_OUT_MSB             (0xF6)
 #define BMP180_REG_OUT_LSB             (0xF7)
 #define BMP180_REG_OUT_XLSB            (0xF8)
 #define RD                             (1)
 #define PORT_N                         (2)
 /* _buf_push expects this scan order */
-#define BMP_DEV_PRES                   (0)
-#define BMP_DEV_TEMP                   (1)
+#define BMP_DEV_PR                   (0)
+#define BMP_DEV_TMP                    (1)
 #define BMP_DEV_N                      (2)
 
 /* regulator names in order of powering on */
@@ -173,15 +159,15 @@ static unsigned short bmp_i2c_addrs[] = {
 };
 
 struct bmp_scale {
-       unsigned long delay_ms;
+       unsigned int delay_ms;
+       u8 os;                          /* oversampling */
        struct nvs_float resolution;
        struct nvs_float milliamp;
 };
 
 struct bmp_hal_dev {
        int version;
-       unsigned int scale_i_max;
-       unsigned int scale_dflt;
+       unsigned int scale_n;
        struct bmp_scale *scale;
        struct nvs_float scale_float;
 };
@@ -234,14 +220,19 @@ struct bmp_state {
        unsigned int sts;               /* status flags */
        unsigned int errs;              /* error count */
        unsigned int enabled;           /* enable status */
+       unsigned int period_us_min;     /* minimum period from MPU */
        unsigned int poll_delay_us;     /* global sampling delay */
        unsigned int delay_us[BMP_DEV_N]; /* sampling delay */
        unsigned int timeout_us[BMP_DEV_N]; /* batch timeout */
        unsigned int scale_i;           /* oversampling index */
        unsigned int scale_user;        /* user oversampling index */
+       unsigned int mpu_bypass_n;      /* allow single bypass call */
+       unsigned int dmp_rd_len_sts;    /* status length from DMP */
+       unsigned int dmp_rd_len_data;   /* data length from DMP */
        u16 i2c_addr;                   /* I2C address */
        u8 dev_id;                      /* device ID */
        bool initd;                     /* set if initialized */
+       bool cmode;                     /* mode normal (continuous) */
        bool mpu_en;                    /* if device behind MPU */
        bool port_en[PORT_N];           /* enable status of MPU write port */
        int port_id[PORT_N];            /* MPU port ID */
@@ -249,15 +240,13 @@ struct bmp_state {
        s32 ut;                         /* uncompensated temperature */
        s32 up;                         /* uncompensated pressure */
        s32 t_fine;                     /* temperature used in pressure calc */
-       s32 temp;                       /* true temperature */
-       int pressure;                   /* true pressure hPa/100 Pa/1 mBar */
-       s64 ts;                         /* sample data timestamp */
+       s32 tmp;                        /* true temperature */
+       u32 prs;                        /* true pressure hPa/100 Pa/1 mBar */
        u8 nvi_config;                  /* NVI configuration */
 };
 
 struct bmp_hal {
-       struct bmp_hal_dev *p;
-       struct bmp_hal_dev *t;
+       struct bmp_hal_dev *dev;
        const char *part;
        u8 rom_addr_start;
        u8 rom_size;
@@ -265,7 +254,13 @@ struct bmp_hal {
        u8 mode_mask;
        struct bmp_cmode *cmode_tbl;
        int (*bmp_read)(struct bmp_state *st);
+#if BMP_NVI_MPU_SUPPORT
        unsigned int mpu_id;
+       u8 port_rd_reg;
+       u8 port_rd_ctrl;
+       void (*port_rd_handler)(u8 *data, unsigned int len,
+                               long long timestamp, void *ext_driver);
+#endif /* BMP_NVI_MPU_SUPPORT */
 };
 
 
@@ -324,15 +319,30 @@ static int bmp_nvi_mpu_bypass_request(struct bmp_state *st)
        int i;
 
        if (st->mpu_en) {
-               for (i = 0; i < BMP_MPU_RETRY_COUNT; i++) {
-                       ret = nvi_mpu_bypass_request(true);
-                       if ((!ret) || (ret == -EPERM))
-                               break;
+               if (!st->mpu_bypass_n) {
+                       for (i = 0; i < BMP_MPU_RETRY_COUNT; i++) {
+                               ret = nvi_mpu_bypass_request(true);
+                               if ((!ret) || (ret == -EPERM))
+                                       break;
 
-                       msleep(BMP_MPU_RETRY_DELAY_MS);
+                               msleep(BMP_MPU_RETRY_DELAY_MS);
+                       }
+
+                       if (ret) {
+                               if (st->sts & NVS_STS_SPEW_MSG)
+                                       dev_err(&st->i2c->dev, "%s err=%d\n",
+                                               __func__, ret);
+                               if (ret == -EPERM)
+                                       ret = 0;
+                       } else {
+                               st->mpu_bypass_n++;
+                               if (st->sts & NVS_STS_SPEW_MSG)
+                                       dev_info(&st->i2c->dev, "%s\n",
+                                                __func__);
+                       }
+               } else {
+                       st->mpu_bypass_n++;
                }
-               if (ret == -EPERM)
-                       ret = 0;
        }
 #endif /* BMP_NVI_MPU_SUPPORT */
        return ret;
@@ -343,8 +353,23 @@ static int bmp_nvi_mpu_bypass_release(struct bmp_state *st)
        int ret = 0;
 
 #if BMP_NVI_MPU_SUPPORT
-       if (st->mpu_en)
-               ret = nvi_mpu_bypass_release();
+       if (st->mpu_en) {
+               if (st->mpu_bypass_n == 1) {
+                       ret = nvi_mpu_bypass_release();
+                       if (ret) {
+                               if (st->sts & NVS_STS_SPEW_MSG)
+                                       dev_err(&st->i2c->dev, "%s err=%d\n",
+                                               __func__, ret);
+                       } else {
+                               st->mpu_bypass_n--;
+                               if (st->sts & NVS_STS_SPEW_MSG)
+                                       dev_info(&st->i2c->dev, "%s\n",
+                                                __func__);
+                       }
+               } else {
+                       st->mpu_bypass_n--;
+               }
+       }
 #endif /* BMP_NVI_MPU_SUPPORT */
        return ret;
 }
@@ -354,12 +379,12 @@ static int bmp_mode_wr(struct bmp_state *st, u8 mode)
        int ret;
 
 #if BMP_NVI_MPU_SUPPORT
-       if (st->mpu_en && !st->i2c->irq) {
+       if (st->mpu_en && !st->cmode) {
                ret = nvi_mpu_data_out(st->port_id[WR], mode);
        } else {
                ret = bmp_nvi_mpu_bypass_request(st);
                if (!ret) {
-                       if (st->i2c->irq) {
+                       if (st->cmode) {
                                ret = bmp_i2c_wr(st, BMP_REG_CTRL,
                                                 BMP_REG_CTRL_MODE_SLEEP);
                                if (mode & st->hal->mode_mask) {
@@ -370,11 +395,17 @@ static int bmp_mode_wr(struct bmp_state *st, u8 mode)
                        } else {
                                ret = bmp_i2c_wr(st, BMP_REG_CTRL, mode);
                        }
+                       if (st->sts & NVS_STS_SPEW_MSG)
+                               dev_info(&st->i2c->dev, "%s mode=%x err=%d\n",
+                                        __func__, mode, ret);
                        bmp_nvi_mpu_bypass_release(st);
                }
        }
 #else /* BMP_NVI_MPU_SUPPORT */
        ret = bmp_i2c_wr(st, BMP_REG_CTRL, mode);
+       if (st->sts & NVS_STS_SPEW_MSG)
+               dev_info(&st->i2c->dev, "%s mode=%x err=%d\n",
+                        __func__, mode, ret);
 #endif /* BMP_NVI_MPU_SUPPORT */
        if (!ret)
                st->data_out = mode;
@@ -391,7 +422,7 @@ static int bmp_pm(struct bmp_state *st, bool enable)
                if (ret)
                        mdelay(BMP_HW_DELAY_POR_MS);
        } else {
-               if (st->i2c->irq) {
+               if (st->cmode) {
                        ret = nvs_vregs_sts(st->vreg, ARRAY_SIZE(bmp_vregs));
                        if ((ret < 0) || (ret == ARRAY_SIZE(bmp_vregs))) {
                                ret = bmp_mode_wr(st, BMP_REG_CTRL_MODE_SLEEP);
@@ -418,17 +449,16 @@ static int bmp_pm(struct bmp_state *st, bool enable)
        return ret;
 }
 
+#if BMP_NVI_MPU_SUPPORT
 static int bmp_port_free(struct bmp_state *st, int port)
 {
        int ret = 0;
 
-#if BMP_NVI_MPU_SUPPORT
        if (st->port_id[port] >= 0) {
                ret = nvi_mpu_port_free(st->port_id[port]);
                if (!ret)
                        st->port_id[port] = -1;
        }
-#endif /* BMP_NVI_MPU_SUPPORT */
        return ret;
 }
 
@@ -440,10 +470,13 @@ static int bmp_ports_free(struct bmp_state *st)
        ret |= bmp_port_free(st, RD);
        return ret;
 }
+#endif /* BMP_NVI_MPU_SUPPORT */
 
 static void bmp_pm_exit(struct bmp_state *st)
 {
+#if BMP_NVI_MPU_SUPPORT
        bmp_ports_free(st);
+#endif /* BMP_NVI_MPU_SUPPORT */
        bmp_pm(st, false);
        nvs_vregs_exit(&st->i2c->dev, st->vreg, ARRAY_SIZE(bmp_vregs));
 }
@@ -452,14 +485,9 @@ static int bmp_pm_init(struct bmp_state *st)
 {
        int ret;
 
-       st->enabled = 0;
-       st->delay_us[BMP_DEV_PRES] = (BMP_POLL_DELAY_MS_DFLT * 1000);
-       st->delay_us[BMP_DEV_TEMP] = (BMP_POLL_DELAY_MS_DFLT * 1000);
+       st->delay_us[BMP_DEV_PRS] = (BMP_POLL_DELAY_MS_DFLT * 1000);
+       st->delay_us[BMP_DEV_TMP] = (BMP_POLL_DELAY_MS_DFLT * 1000);
        st->poll_delay_us = (BMP_POLL_DELAY_MS_DFLT * 1000);
-       st->initd = false;
-       st->mpu_en = false;
-       st->port_en[WR] = false;
-       st->port_en[RD] = false;
        st->port_id[WR] = -1;
        st->port_id[RD] = -1;
        nvs_vregs_init(&st->i2c->dev,
@@ -468,10 +496,10 @@ static int bmp_pm_init(struct bmp_state *st)
        return ret;
 }
 
+#if BMP_NVI_MPU_SUPPORT
 static int bmp_ports_enable(struct bmp_state *st, bool enable)
 {
        int ret = 0;
-#if BMP_NVI_MPU_SUPPORT
        unsigned int port_mask = 0;
        unsigned int i;
 
@@ -490,10 +518,9 @@ static int bmp_ports_enable(struct bmp_state *st, bool enable)
                        }
                }
        }
-#endif /* BMP_NVI_MPU_SUPPORT */
-
        return ret;
 }
+#endif /* BMP_NVI_MPU_SUPPORT */
 
 static int bmp_wr(struct bmp_state *st, u8 reg, u8 val)
 {
@@ -507,47 +534,151 @@ static int bmp_wr(struct bmp_state *st, u8 reg, u8 val)
        return ret;
 }
 
-static int bmp_mode(struct bmp_state *st)
+static unsigned int bmp_cmode_t(struct bmp_state *st, u8 *t_sb,
+                               unsigned int period_us, unsigned int scale_i)
+{
+       unsigned int us = 0;
+       unsigned int i = 0;
+
+
+       while (st->hal->cmode_tbl[i].t_us) {
+               *t_sb = st->hal->cmode_tbl[i].t_sb;
+               us = st->hal->cmode_tbl[i].t_us;
+               us += st->hal->dev[BMP_DEV_PRS].scale[scale_i].delay_ms * 1000;
+               if (period_us >= us)
+                       return us;
+
+               i++;
+               if ((!st->mpu_en) && st->hal->cmode_tbl[i].t_us) {
+                       us -= st->hal->cmode_tbl[i].t_us;
+                       us >>= 1;
+                       us += st->hal->cmode_tbl[i].t_us;
+                       us += st->hal->dev[BMP_DEV_PRS].scale[scale_i].
+                                                              delay_ms * 1000;
+                       if (period_us > us)
+                               return us;
+               }
+       }
+
+       return us;
+}
+
+static int bmp_mode(struct bmp_state *st, unsigned int period_us,
+                   unsigned int scale_user, unsigned int enable)
 {
        u8 mode;
        u8 t_sb;
-       unsigned int t_us;
        unsigned int i;
-       int ret;
-
-       if (st->dev_id == BMP_REG_ID_BMP180) {
-               mode = st->scale_i << BMP180_REG_CTRL_OSS;
-               mode |= BMP180_REG_CTRL_MODE_TEMP;
-       } else {
-               mode = st->scale_i + 1;
-               mode = ((mode << BMP280_REG_CTRL_OSRS_T) |
-                       (mode << BMP280_REG_CTRL_OSRS_P));
-               mode |= BMP280_REG_CTRL_MODE_FORCED1;
-       }
-       if (st->i2c->irq) {
-               i = 0;
-               t_sb = 0;
-               while (st->hal->cmode_tbl[i].t_us) {
-                       t_sb = st->hal->cmode_tbl[i].t_sb;
-                       t_us = st->hal->cmode_tbl[i].t_us;
-                       if (st->poll_delay_us >=
-                                           st->hal->cmode_tbl[i].t_us)
-                               break;
+       unsigned int scale_i;
+       unsigned int us = 0;
+       int ret = 0;
 
-                       i++;
-                       if (!st->mpu_en) {
-                               t_us -= st->hal->cmode_tbl[i].t_us;
-                               t_us >>= 1;
-                               t_us += st->hal->cmode_tbl[i].t_us;
-                               if (st->poll_delay_us > t_us)
+       i = BMP_DEV_PRS;
+       if (st->cmode) {
+               if (scale_user) {
+                       /* static scale mode */
+                       scale_i = scale_user - 1;
+                       us = bmp_cmode_t(st, &t_sb, period_us, scale_i);
+               } else {
+                       /* auto scale mode - matching scale to the period */
+                       scale_i = 0;
+                       for (; scale_i < st->hal->dev[i].scale_n; scale_i++) {
+                               us = bmp_cmode_t(st, &t_sb,
+                                                period_us, scale_i);
+                               if (period_us >= us)
+                                       /* HW (us) is fast enough */
                                        break;
                        }
+
+                       if (scale_i >= st->hal->dev[i].scale_n)
+                               scale_i = st->hal->dev[i].scale_n - 1;
                }
+
+               if (period_us < us)
+                       period_us = us;
+               mode = BMP280_REG_CTRL_MODE_NORMAL;
+               mode |= st->hal->dev[BMP_DEV_TMP].scale[scale_i].os <<
+                                                       BMP280_REG_CTRL_OSRS_T;
+               if (enable & (1 << BMP_DEV_PRS))
+                       mode |= st->hal->dev[BMP_DEV_PRS].scale[scale_i].os <<
+                                                       BMP280_REG_CTRL_OSRS_P;
+               /* else presure will be disabled */
                t_sb <<= BMP280_REG_CONFIG_T_SB;
-               bmp_wr(st, BMP280_REG_CONFIG, t_sb);
-               mode |= BMP280_REG_CTRL_MODE_NORMAL;
+               ret = bmp_nvi_mpu_bypass_request(st);
+               if (!ret) {
+                       ret = bmp_wr(st, BMP280_REG_CONFIG, t_sb);
+                       if (ret)
+                               mode = BMP_REG_CTRL_MODE_SLEEP;
+                       if (st->sts & NVS_STS_SPEW_MSG)
+                               dev_info(&st->i2c->dev, "%s cfg=%x err=%d\n",
+                                        __func__, t_sb, ret);
+                       ret |= bmp_mode_wr(st, mode);
+                       bmp_nvi_mpu_bypass_release(st);
+               }
+       } else {
+               if (scale_user) {
+                       scale_i = scale_user - 1;
+                       us = st->hal->dev[i].scale[scale_i].delay_ms * 1000;
+               } else {
+                       /* scale is automatic based on period */
+                       scale_i = 0;
+                       for (; scale_i < st->hal->dev[i].scale_n; scale_i++) {
+                               us = st->hal->dev[i].scale[scale_i].delay_ms;
+                               us *= 1000;
+                               if (period_us >= us)
+                                       /* HW (us) is fast enough */
+                                       break;
+                       }
+
+                       if (scale_i >= st->hal->dev[i].scale_n)
+                               scale_i = st->hal->dev[i].scale_n - 1;
+               }
+
+               if (period_us < us)
+                       period_us = us;
+#if BMP_NVI_MPU_SUPPORT
+               if (scale_i != st->scale_i && st->mpu_en &&
+                                                         st->port_id[WR] >= 0)
+                       ret = nvi_mpu_delay_ms(st->port_id[WR],
+                                     st->hal->dev[i].scale[scale_i].delay_ms);
+#endif /* BMP_NVI_MPU_SUPPORT */
+               if (st->dev_id == BMP_REG_ID_BMP180) {
+                       mode = st->hal->dev[i].scale[scale_i].os <<
+                                                          BMP180_REG_CTRL_OSS;
+                       mode |= BMP180_REG_CTRL_MODE_TEMP;
+               } else {
+                       mode = BMP280_REG_CTRL_MODE_FORCED1;
+                       mode |= st->hal->dev[BMP_DEV_TMP].scale[scale_i].os <<
+                                                       BMP280_REG_CTRL_OSRS_T;
+                       if (enable & (1 << BMP_DEV_PRS))
+                               mode |= st->hal->dev[i].scale[scale_i].os <<
+                                                       BMP280_REG_CTRL_OSRS_P;
+               }
+               ret |= bmp_mode_wr(st, mode);
+       }
+       if (!ret) {
+               if (period_us != st->poll_delay_us) {
+                       if (st->sts & NVS_STS_SPEW_MSG)
+                               dev_info(&st->i2c->dev, "%s: period_us=%u\n",
+                                        __func__, period_us);
+#if BMP_NVI_MPU_SUPPORT
+                       if (st->mpu_en) {
+                               us = -1;
+                               for (i = 0; i < BMP_DEV_N; i++) {
+                                       if ((enable & (1 << i)) &&
+                                                       st->timeout_us[i] < us)
+                                               us = st->timeout_us[i];
+                               }
+                               ret = nvi_mpu_batch(st->port_id[RD],
+                                                   period_us, us);
+                       }
+                       if (!ret)
+#endif /* BMP_NVI_MPU_SUPPORT */
+                               st->poll_delay_us = period_us;
+               }
+               if (!ret)
+                       st->scale_i = scale_i;
        }
-       ret = bmp_mode_wr(st, mode);
        return ret;
 }
 
@@ -556,21 +687,22 @@ static void bmp_calc_180(struct bmp_state *st)
        long X1, X2, X3, B3, B5, B6, p;
        unsigned long B4, B7;
        long pressure;
+       u8 oss = st->hal->dev[BMP_DEV_PRS].scale[st->scale_i].os;
 
        X1 = ((st->ut - st->rom.bmp180.ac6) * st->rom.bmp180.ac5) >> 15;
        X2 = st->rom.bmp180.mc * (1 << 11) / (X1 + st->rom.bmp180.md);
        B5 = X1 + X2;
-       st->temp = (B5 + 8) >> 4;
+       st->tmp = (B5 + 8) >> 4;
        B6 = B5 - 4000;
        X1 = (st->rom.bmp180.b2 * ((B6 * B6) >> 12)) >> 11;
        X2 = (st->rom.bmp180.ac2 * B6) >> 11;
        X3 = X1 + X2;
-       B3 = ((((st->rom.bmp180.ac1 << 2) + X3) << st->scale_i) + 2) >> 2;
+       B3 = ((((st->rom.bmp180.ac1 << 2) + X3) << oss) + 2) >> 2;
        X1 = (st->rom.bmp180.ac3 * B6) >> 13;
        X2 = (st->rom.bmp180.b1 * ((B6 * B6) >> 12)) >> 16;
        X3 = ((X1 + X2) + 2) >> 2;
        B4 = (st->rom.bmp180.ac4 * (unsigned long)(X3 + 32768)) >> 15;
-       B7 = ((unsigned long)st->up - B3) * (50000 >> st->scale_i);
+       B7 = ((unsigned long)st->up - B3) * (50000 >> oss);
        if (B7 < 0x80000000)
                p = (B7 << 1) / B4;
        else
@@ -579,28 +711,29 @@ static void bmp_calc_180(struct bmp_state *st)
        X1 = (X1 * 3038) >> 16;
        X2 = (-7357 * p) >> 16;
        pressure = p + ((X1 + X2 + 3791) >> 4);
-       st->pressure = (int)pressure;
+       st->prs = (int)pressure;
 }
 
 static int bmp_read_sts_180(struct bmp_state *st, u8 *data, s64 ts)
 {
+       u8 oss;
        s32 val;
        int ret = 0;
 
        /* BMP180_REG_CTRL_SCO is 0 when data is ready */
        if (!(data[0] & (1 << BMP180_REG_CTRL_SCO))) {
+               oss = st->hal->dev[BMP_DEV_PRS].scale[st->scale_i].os;
                ret = -1;
                if (data[0] == 0x0A) { /* temperature */
                        st->ut = ((data[2] << 8) + data[3]);
                        st->data_out = BMP180_REG_CTRL_MODE_PRES |
-                                       (st->scale_i << BMP180_REG_CTRL_OSS);
+                                                 (oss << BMP180_REG_CTRL_OSS);
                } else { /* pressure */
-                       val = ((data[2] << 16) + (data[3] << 8) +
-                                               data[4]) >> (8 - st->scale_i);
+                       val = ((data[2] << 16) + (data[3] << 8) + data[4]);
+                       val >>= (8 - oss);
                        st->data_out = BMP180_REG_CTRL_MODE_TEMP;
                        st->up = val;
                        bmp_calc_180(st);
-                       st->ts = ts;
                        ret = 1;
                }
        }
@@ -620,12 +753,13 @@ static int bmp_read_180(struct bmp_state *st)
        ts = nvs_timestamp();
        ret = bmp_read_sts_180(st, data, ts);
        if (ret > 0) {
-               if (st->nvs_st[BMP_DEV_PRES])
-                       st->nvs->handler(st->nvs_st[BMP_DEV_PRES],
-                                        &st->pressure, ts);
-               if (st->nvs_st[BMP_DEV_TEMP])
-                       st->nvs->handler(st->nvs_st[BMP_DEV_TEMP],
-                                        &st->temp, ts);
+               if (st->enabled & (1 << BMP_DEV_PRS))
+                       st->nvs->handler(st->nvs_st[BMP_DEV_PRS],
+                                        &st->prs, ts);
+               if (st->enabled & (1 << BMP_DEV_TMP))
+                       /* nvs handles on-change sensor timing & same values */
+                       st->nvs->handler(st->nvs_st[BMP_DEV_TMP],
+                                        &st->tmp, ts);
                bmp_i2c_wr(st, BMP_REG_CTRL, st->data_out);
        } else if (ret < 0) {
                bmp_i2c_wr(st, BMP_REG_CTRL, st->data_out);
@@ -635,75 +769,81 @@ static int bmp_read_180(struct bmp_state *st)
 
 static void bmp_calc_temp_280(struct bmp_state *st)
 {
-       s32 adc_t;
        s32 var1;
        s32 var2;
 
-       adc_t = st->ut;
-       adc_t >>= (4 - st->scale_i);
-       var1 = adc_t >> 3;
-       var1 -= ((s32)st->rom.bmp280.dig_T1 << 1);
-       var1 *= (s32)st->rom.bmp280.dig_T2;
+       var1 = st->ut;
+       var1 >>= 3;
+       var2 = st->rom.bmp280.dig_T1;
+       var2 <<= 1;
+       var1 -= var2;
+       var1 *= st->rom.bmp280.dig_T2;
        var1 >>= 11;
-       var2 = adc_t >> 4;
+       var2 = st->ut;
+       var2 >>= 4;
        var2 -= (s32)st->rom.bmp280.dig_T1;
        var2 *= var2;
        var2 >>= 12;
-       var2 *= (s32)st->rom.bmp280.dig_T3;
+       var2 *= st->rom.bmp280.dig_T3;
        var2 >>= 14;
        st->t_fine = var1 + var2;
-       st->temp = (st->t_fine * 5 + 128) >> 8;
+       st->tmp = (st->t_fine * 5 + 128) >> 8;
 }
 
 static int bmp_calc_pres_280(struct bmp_state *st)
 {
-       s32 adc_p;
-       s32 var1;
-       s32 var2;
-       s32 var3;
-       u32 p;
-
-       adc_p = st->up;
-       var1 = st->t_fine >> 1;
-       var1 -= 64000;
-       var2 = var1 >> 2;
-       var2 *= var2;
-       var3 = var2;
-       var2 >>= 11;
+       s64 var1;
+       s64 var2;
+       s64 var3;
+       s64 p;
+
+       var1 = st->t_fine;
+       var1 -= 128000;
+       var2 = var1 * var1;
        var2 *= st->rom.bmp280.dig_P6;
-       var2 += ((var1 * st->rom.bmp280.dig_P5) << 1);
-       var2 >>= 2;
-       var2 += (st->rom.bmp280.dig_P4 << 16);
-       var3 >>= 13;
-       var3 *= st->rom.bmp280.dig_P3;
-       var3 >>= 3;
-       var1 *= st->rom.bmp280.dig_P2;
-       var1 >>= 1;
+       var3 = st->rom.bmp280.dig_P5;
+       var3 *= var1;
+       var3 <<= 17;
+       var2 += var3;
+       var3 = st->rom.bmp280.dig_P4;
+       var3 <<= 35;
+       var2 += var3;
+       var3 = var1;
+       var3 *= st->rom.bmp280.dig_P2;
+       var3 <<= 12;
+       var1 *= var1;
+       var1 *= st->rom.bmp280.dig_P3;
+       var1 >>= 8;
+       var1 += var3;
+       var3 = 1;
+       var3 <<= 47;
        var1 += var3;
-       var1 >>= 18;
-       var1 += 32768;
        var1 *= st->rom.bmp280.dig_P1;
-       var1 >>= 15;
+       var1 >>= 33;
        if (!var1)
                return -1;
 
-       p = ((u32)(((s32)1048576) - adc_p) - (var2 >> 12)) * 3125;
-       if (p < 0x80000000)
-               p = (p << 1) / ((u32)var1);
-       else
-               p = (p / (u32)var1) << 1;
-       var3 = p >> 3;
-       var3 *= var3;
-       var3 >>= 13;
-       var1 = (s32)st->rom.bmp280.dig_P9 * var3;
-       var1 >>= 12;
-       var2 = (s32)(p >> 2);
-       var2 *= (s32)st->rom.bmp280.dig_P8;
-       var2 >>= 13;
-       var3 = var1 + var2 + st->rom.bmp280.dig_P7;
-       var3 >>= 4;
-       p = (u32)((s32)p + var3);
-       st->pressure = (int)p;
+       p = 1048576 - st->up;
+       p <<= 31;
+       p -= var2;
+       p *= 3125;
+       p = div64_s64(p, var1);
+       var1 = p;
+       var1 >>= 13;
+       var1 *= var1;
+       var1 *= st->rom.bmp280.dig_P9;
+       var1 >>= 25;
+       var2 = st->rom.bmp280.dig_P8;
+       var2 *= p;
+       var2 >>= 19;
+       var3 = st->rom.bmp280.dig_P7;
+       var3 <<= 4;
+       p += var1;
+       p += var2;
+       p >>= 8;
+       p += var3;
+       p >>= 8;
+       st->prs = (u32)p;
        return 1;
 }
 
@@ -721,16 +861,17 @@ static int bmp_push_280(struct bmp_state *st, u8 *data, s64 ts)
        val >>= 4;
        st->ut = val;
        bmp_calc_temp_280(st);
-       ret = bmp_calc_pres_280(st);
-       if (ret > 0) {
-               st->ts = ts;
-               if (st->nvs_st[BMP_DEV_PRES])
-                       st->nvs->handler(st->nvs_st[BMP_DEV_PRES],
-                                        &st->pressure, ts);
-               if (st->nvs_st[BMP_DEV_TEMP])
-                       st->nvs->handler(st->nvs_st[BMP_DEV_TEMP],
-                                        &st->temp, ts);
+       if (st->enabled & (1 << BMP_DEV_PRS)) {
+               ret = bmp_calc_pres_280(st);
+               if (ret > 0)
+                       st->nvs->handler(st->nvs_st[BMP_DEV_PRS],
+                                        &st->prs, ts);
+       } else {
+               ret = 1;
        }
+       if (st->enabled & (1 << BMP_DEV_TMP))
+               /* nvs handles on-change sensor timing & same values */
+               st->nvs->handler(st->nvs_st[BMP_DEV_TMP], &st->tmp, ts);
        return ret;
 }
 
@@ -784,7 +925,11 @@ static void bmp_mpu_handler_280(u8 *data, unsigned int len, s64 ts, void *p_val)
        }
 
        if (st->enabled) {
-               if (len == 6) {
+               if (len == st->dmp_rd_len_sts)
+                       /* status data from the DMP not supported */
+                       return;
+
+               if (len == st->dmp_rd_len_data) {
                        /* this data is from the DMP */
                        i = 0;
                        ret = 1;
@@ -816,19 +961,18 @@ static void bmp_mpu_handler_180(u8 *data, unsigned int len, s64 ts, void *p_val)
                return;
        }
 
-       if (st->enabled) {
-               ret = bmp_read_sts_180(st, data, ts);
-               if (ret > 0) {
-                       if (st->nvs_st[BMP_DEV_PRES])
-                               st->nvs->handler(st->nvs_st[BMP_DEV_PRES],
-                                                &st->pressure, ts);
-                       if (st->nvs_st[BMP_DEV_TEMP])
-                               st->nvs->handler(st->nvs_st[BMP_DEV_TEMP],
-                                                &st->temp, ts);
-                       nvi_mpu_data_out(st->port_id[WR], st->data_out);
-               } else if (ret < 0) {
-                       nvi_mpu_data_out(st->port_id[WR], st->data_out);
-               }
+       ret = bmp_read_sts_180(st, data, ts);
+       if (ret > 0) {
+               if (st->enabled & (1 << BMP_DEV_PRS))
+                       st->nvs->handler(st->nvs_st[BMP_DEV_PRS],
+                                        &st->prs, ts);
+               if (st->enabled & (1 << BMP_DEV_TMP))
+                       /* nvs handles on-change sensor timing & same values */
+                       st->nvs->handler(st->nvs_st[BMP_DEV_TMP],
+                                        &st->tmp, ts);
+               nvi_mpu_data_out(st->port_id[WR], st->data_out);
+       } else if (ret < 0) {
+               nvi_mpu_data_out(st->port_id[WR], st->data_out);
        }
 }
 #endif /* BMP_NVI_MPU_SUPPORT */
@@ -850,78 +994,25 @@ static void bmp_work(struct work_struct *ws)
                st->nvs->nvs_mutex_unlock(st->nvs_st[i]);
 }
 
-static unsigned int bmp_poll_delay(struct bmp_state *st)
+static unsigned int bmp_poll_delay(struct bmp_state *st, unsigned int en_msk)
 {
        unsigned int i;
        unsigned int delay_us = -1;
+       bool valid = false;
 
        for (i = 0; i < BMP_DEV_N; i++) {
-               if (st->enabled & (1 << i)) {
-                       if (st->delay_us[i] < delay_us)
+               if (en_msk & (1 << i)) {
+                       if (st->delay_us[i] && st->delay_us[i] < delay_us) {
                                delay_us = st->delay_us[i];
+                               valid = true;
+                       }
                }
        }
-       if (delay_us == -1)
+       if (!valid)
                delay_us = (BMP_POLL_DELAY_MS_DFLT * 1000);
        return delay_us;
 }
 
-static int bmp_delay(struct bmp_state *st,
-                    unsigned int delay_us, int scale_user)
-{
-       unsigned int timeout;
-       unsigned int i;
-       int ret;
-       int ret_t = 0;
-
-       if (scale_user) {
-               i = scale_user - 1;
-       } else {
-               for (i = (st->hal->p->scale_i_max - 1); i > 0; i--) {
-                       if (delay_us >= (st->hal->p->scale[i].delay_ms * 1000))
-                               break;
-               }
-       }
-       if (i != st->scale_i) {
-               ret = 0;
-#if BMP_NVI_MPU_SUPPORT
-               if (st->mpu_en)
-                       ret = nvi_mpu_delay_ms(st->port_id[WR],
-                                              st->hal->p->scale[i].delay_ms);
-#endif /* BMP_NVI_MPU_SUPPORT */
-               if (ret < 0)
-                       ret_t |= ret;
-               else
-                       st->scale_i = i;
-       }
-       if (delay_us < (st->hal->p->scale[st->scale_i].delay_ms * 1000))
-               delay_us = (st->hal->p->scale[st->scale_i].delay_ms * 1000);
-       if (delay_us != st->poll_delay_us) {
-               if (st->sts & NVS_STS_SPEW_MSG)
-                       dev_info(&st->i2c->dev, "%s: %u\n",
-                                __func__, delay_us);
-#if BMP_NVI_MPU_SUPPORT
-               ret = 0;
-               if (st->mpu_en) {
-                       timeout = -1;
-                       for (i = 0; i < BMP_DEV_N; i++) {
-                               if (st->enabled & (1 << i)) {
-                                       if (st->timeout_us[i] < timeout)
-                                               timeout = st->timeout_us[i];
-                               }
-                       }
-                       ret = nvi_mpu_batch(st->port_id[RD],
-                                           delay_us, timeout);
-               }
-               if (ret)
-                       ret_t |= ret;
-               else
-#endif /* BMP_NVI_MPU_SUPPORT */
-                       st->poll_delay_us = delay_us;
-       }
-       return ret_t;
-}
-
 static int bmp_init_hw(struct bmp_state *st)
 {
        u8 *p_rom8;
@@ -931,8 +1022,8 @@ static int bmp_init_hw(struct bmp_state *st)
 
        st->ut = 0;
        st->up = 0;
-       st->temp = 0;
-       st->pressure = 0;
+       st->tmp = 0;
+       st->prs = 0;
        p_rom8 = (u8 *)&st->rom;
        ret = bmp_nvi_mpu_bypass_request(st);
        if (!ret) {
@@ -957,6 +1048,7 @@ static int bmp_init_hw(struct bmp_state *st)
 
 static int bmp_dis(struct bmp_state *st)
 {
+#if BMP_NVI_MPU_SUPPORT
        int ret = 0;
 
        if (st->mpu_en)
@@ -966,6 +1058,11 @@ static int bmp_dis(struct bmp_state *st)
        if (!ret)
                st->enabled = 0;
        return ret;
+#else /* BMP_NVI_MPU_SUPPORT */
+       cancel_delayed_work(&st->dw);
+       st->enabled = 0;
+       return 0;
+#endif /* BMP_NVI_MPU_SUPPORT */
 }
 
 static int bmp_disable(struct bmp_state *st, int snsr_id)
@@ -1009,11 +1106,12 @@ static int bmp_enable(void *client, int snsr_id, int enable)
                enable = st->enabled | (1 << snsr_id);
                ret = bmp_en(st);
                if (!ret) {
-                       ret |= bmp_delay(st, bmp_poll_delay(st),
-                                        st->scale_user);
-                       ret |= bmp_mode(st);
+                       ret = bmp_mode(st, bmp_poll_delay(st, enable),
+                                      st->scale_user, enable);
+#if BMP_NVI_MPU_SUPPORT
                        if (st->mpu_en)
                                ret |= bmp_ports_enable(st, true);
+#endif /* BMP_NVI_MPU_SUPPORT */
                        if (ret) {
                                bmp_disable(st, snsr_id);
                        } else {
@@ -1034,9 +1132,9 @@ static int bmp_batch(void *client, int snsr_id, int flags,
                     unsigned int period, unsigned int timeout)
 {
        struct bmp_state *st = (struct bmp_state *)client;
+       int ret = 0;
        unsigned int old_period;
        unsigned int old_timeout;
-       int ret;
 
        if (timeout && !st->mpu_en)
                /* timeout not supported (no HW FIFO) */
@@ -1046,14 +1144,15 @@ static int bmp_batch(void *client, int snsr_id, int flags,
        old_timeout = st->timeout_us[snsr_id];
        st->delay_us[snsr_id] = period;
        st->timeout_us[snsr_id] = timeout;
-       ret = bmp_delay(st, bmp_poll_delay(st), st->scale_user);
-       if (st->enabled && st->i2c->irq && !ret)
-               ret = bmp_mode(st);
-       if (ret) {
-               st->delay_us[snsr_id] = old_period;
-               st->timeout_us[snsr_id] = old_timeout;
+       if (st->enabled) {
+               ret = bmp_mode(st, bmp_poll_delay(st, st->enabled),
+                              st->scale_user, st->enabled);
+               if (ret) {
+                       st->delay_us[snsr_id] = old_period;
+                       st->timeout_us[snsr_id] = old_timeout;
+               }
        }
-       return 0;
+       return ret;
 }
 
 static int bmp_flush(void *client, int snsr_id)
@@ -1065,49 +1164,51 @@ static int bmp_flush(void *client, int snsr_id)
        if (st->mpu_en)
                ret = nvi_mpu_flush(st->port_id[RD]);
 #endif /* BMP_NVI_MPU_SUPPORT */
+
        return ret;
 }
 
 static int bmp_resolution(void *client, int snsr_id, int resolution)
 {
        struct bmp_state *st = (struct bmp_state *)client;
+       unsigned int us;
+       unsigned int i;
        int ret;
 
-       if (snsr_id != BMP_DEV_PRES)
+       if (snsr_id != BMP_DEV_PRS)
                return -EINVAL;
 
-       if (resolution < 0 || resolution > st->hal->p->scale_i_max)
-               return -EINVAL;
+       if (resolution < 0)
+               resolution = 0;
+       if (resolution > st->hal->dev[BMP_DEV_PRS].scale_n)
+               resolution = st->hal->dev[BMP_DEV_PRS].scale_n;
+       if (st->enabled) {
+               ret = bmp_mode(st, st->poll_delay_us, resolution, st->enabled);
+               if (ret)
+                       return ret;
+       } else {
+               if (resolution)
+                       st->scale_i = resolution - 1;
+               else
+                       st->scale_i = 0;
+       }
 
-       ret = bmp_delay(st, st->poll_delay_us, resolution);
-       if (!ret) {
-               st->scale_user = resolution;
-               if (st->enabled && st->i2c->irq)
-                       ret = bmp_mode(st);
+       st->scale_user = resolution;
+       for (i = 0; i < BMP_DEV_N; i++) {
+               st->cfg[i].resolution.ival =
+                           st->hal->dev[i].scale[st->scale_i].resolution.ival;
+               st->cfg[i].resolution.fval =
+                           st->hal->dev[i].scale[st->scale_i].resolution.fval;
+               st->cfg[i].milliamp.ival =
+                             st->hal->dev[i].scale[st->scale_i].milliamp.ival;
+               st->cfg[i].milliamp.fval =
+                             st->hal->dev[i].scale[st->scale_i].milliamp.fval;
+               us = st->hal->dev[i].scale[st->scale_i].delay_ms * 1000;
+               if (us < st->period_us_min)
+                       us = st->period_us_min;
+               st->cfg[i].delay_us_min = us;
        }
-       if (ret)
-               return ret;
 
-       st->cfg[BMP_DEV_PRES].resolution.ival =
-                               st->hal->p->scale[st->scale_i].resolution.ival;
-       st->cfg[BMP_DEV_PRES].resolution.fval =
-                               st->hal->p->scale[st->scale_i].resolution.fval;
-       st->cfg[BMP_DEV_PRES].milliamp.ival =
-                                 st->hal->p->scale[st->scale_i].milliamp.ival;
-       st->cfg[BMP_DEV_PRES].milliamp.fval =
-                                 st->hal->p->scale[st->scale_i].milliamp.fval;
-       st->cfg[BMP_DEV_PRES].delay_us_min =
-                               st->hal->p->scale[st->scale_i].delay_ms * 1000;
-       st->cfg[BMP_DEV_TEMP].resolution.ival =
-                               st->hal->t->scale[st->scale_i].resolution.ival;
-       st->cfg[BMP_DEV_TEMP].resolution.fval =
-                               st->hal->t->scale[st->scale_i].resolution.fval;
-       st->cfg[BMP_DEV_TEMP].milliamp.ival =
-                                 st->hal->t->scale[st->scale_i].milliamp.ival;
-       st->cfg[BMP_DEV_TEMP].milliamp.fval =
-                                 st->hal->t->scale[st->scale_i].milliamp.fval;
-       st->cfg[BMP_DEV_TEMP].delay_us_min =
-                               st->hal->t->scale[st->scale_i].delay_ms * 1000;
        return 0;
 }
 
@@ -1138,14 +1239,13 @@ static int bmp_regs(void *client, int snsr_id, char *buf)
        int ret;
 
        if (!st->initd) {
-               t = sprintf(buf, "calibration: NEED ENABLE\n");
+               t = snprintf(buf, PAGE_SIZE, "calibration: NEED ENABLE\n");
        } else {
-               t = sprintf(buf, "calibration:\n");
+               t = snprintf(buf, PAGE_SIZE, "calibration:\n");
                cal = &st->rom.bmp280.dig_T1;
                for (i = 0; i < st->hal->rom_size; i = i + 2)
-                       t += sprintf(buf + t, "%#2x=%#2x\n",
-                                    st->hal->rom_addr_start + i,
-                                    *cal++);
+                       t += snprintf(buf + t, PAGE_SIZE - t, "%#2x=%#2x\n",
+                                     st->hal->rom_addr_start + i, *cal++);
        }
        ret = bmp_nvi_mpu_bypass_request(st);
        if (!ret) {
@@ -1155,15 +1255,15 @@ static int bmp_regs(void *client, int snsr_id, char *buf)
                bmp_nvi_mpu_bypass_release(st);
        }
        if (ret) {
-               t += sprintf(buf + t, "registers: ERR %d\n", ret);
+               t += snprintf(buf + t, PAGE_SIZE - t,
+                             "registers: ERR %d\n", ret);
        } else {
-               t += sprintf(buf + t, "registers:\n");
-               t += sprintf(buf + t, "%#2x=%#2x\n",
-                            BMP_REG_ID, data[0]);
+               t += snprintf(buf + t, PAGE_SIZE - t, "registers:\n");
+               t += snprintf(buf + t, PAGE_SIZE - t, "%#2x=%#2x\n",
+                             BMP_REG_ID, data[0]);
                for (i = 0; i < 10; i++)
-                       t += sprintf(buf + t, "%#2x=%#2x\n",
-                                    BMP280_REG_STATUS + i,
-                                    data[i + 1]);
+                       t += snprintf(buf + t, PAGE_SIZE - t, "%#2x=%#2x\n",
+                                     BMP280_REG_STATUS + i, data[i + 1]);
        }
        return t;
 }
@@ -1173,9 +1273,14 @@ static int bmp_nvs_read(void *client, int snsr_id, char *buf)
        struct bmp_state *st = (struct bmp_state *)client;
        ssize_t t;
 
-       t = sprintf(buf, "driver v.%u\n", BMP_DRIVER_VERSION);
-       t += sprintf(buf + t, "mpu_en=%x\n", st->mpu_en);
-       t += sprintf(buf + t, "nvi_config=%hhu\n", st->nvi_config);
+       t = snprintf(buf, PAGE_SIZE, "driver v.%u\n", BMP_DRIVER_VERSION);
+       t += snprintf(buf + t, PAGE_SIZE - t, "mpu_en=%x\n", st->mpu_en);
+       t += snprintf(buf + t, PAGE_SIZE - t, "nvi_config=%hhu\n",
+                     st->nvi_config);
+       t += snprintf(buf + t, PAGE_SIZE - t, "cmode_enable=%x\n", st->cmode);
+       if (!st->scale_user)
+               t += snprintf(buf + t, PAGE_SIZE - t, "scale_user=auto\n");
+       t += snprintf(buf + t, PAGE_SIZE - t, "scale_i=%x\n", st->scale_i);
        return t;
 }
 
@@ -1267,7 +1372,7 @@ static int bmp_remove(struct i2c_client *client)
 struct sensor_cfg bmp_cfg_dflt[] = {
        {
                .name                   = "pressure",
-               .snsr_id                = BMP_DEV_PRES,
+               .snsr_id                = BMP_DEV_PRS,
                .kbuf_sz                = BMP_KBUF_SIZE,
                .ch_n                   = 1,
                .ch_sz                  = -4,
@@ -1278,12 +1383,10 @@ struct sensor_cfg bmp_cfg_dflt[] = {
                        .ival           = BMP_PRES_MAX_RANGE_IVAL,
                        .fval           = BMP_PRES_MAX_RANGE_MICRO,
                },
-               .delay_us_min           = 10000,
-               .delay_us_max           = 255000,
        },
        {
                .name                   = "ambient_temperature",
-               .snsr_id                = BMP_DEV_TEMP,
+               .snsr_id                = BMP_DEV_TMP,
                .ch_n                   = 1,
                .ch_sz                  = -4,
                .part                   = BMP_NAME,
@@ -1293,131 +1396,131 @@ struct sensor_cfg bmp_cfg_dflt[] = {
                        .ival           = BMP_TEMP_MAX_RANGE_IVAL,
                        .fval           = BMP_TEMP_MAX_RANGE_MICRO,
                },
-               .delay_us_min           = 10000,
-               .delay_us_max           = 255000,
                .flags                  = SENSOR_FLAG_ON_CHANGE_MODE,
        },
 };
 
-static struct bmp_scale bmp_scale_pres_180[] = {
+static struct bmp_scale bmp_scale_prs_180[] = {
        {
-               .delay_ms               = 5,
+               .delay_ms               = 26,
+               .os                     = 0x03,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 10000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 3000,
+                       .fval           = 12000,
                },
        },
        {
-               .delay_ms               = 8,
+               .delay_ms               = 14,
+               .os                     = 0x02,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 10000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 5000,
+                       .fval           = 7000,
                },
        },
        {
-               .delay_ms               = 14,
+               .delay_ms               = 8,
+               .os                     = 0x01,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 10000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 7000,
+                       .fval           = 5000,
                },
        },
        {
-               .delay_ms               = 26,
+               .delay_ms               = 5,
+               .os                     = 0x00,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 10000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 12000,
+                       .fval           = 3000,
                },
        },
 };
 
-static struct bmp_scale bmp_scale_temp_180[] = {
+static struct bmp_scale bmp_scale_tmp_180[] = {
        {
-               .delay_ms               = 5,
+               .delay_ms               = 26,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 100000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 3000,
+                       .fval           = 12000,
                },
        },
        {
-               .delay_ms               = 8,
+               .delay_ms               = 14,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 100000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 5000,
+                       .fval           = 7000,
                },
        },
        {
-               .delay_ms               = 14,
+               .delay_ms               = 8,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 100000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 7000,
+                       .fval           = 5000,
                },
        },
        {
-               .delay_ms               = 26,
+               .delay_ms               = 5,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 100000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 12000,
+                       .fval           = 3000,
                },
        },
 };
 
-static struct bmp_hal_dev bmp_hal_dev_pres_180 = {
-       .version                        = 1,
-       .scale_i_max                    = ARRAY_SIZE(bmp_scale_pres_180),
-       .scale_dflt                     = BMP180_RANGE_DFLT,
-       .scale                          = bmp_scale_pres_180,
-       .scale_float                    = {
-               .ival                   = 0,
-               .fval                   = 10000,
-       }
-};
-
-static struct bmp_hal_dev bmp_hal_dev_temp_180 = {
-       .version                        = 1,
-       .scale_i_max                    = ARRAY_SIZE(bmp_scale_temp_180),
-       .scale_dflt                     = BMP180_RANGE_DFLT,
-       .scale                          = bmp_scale_temp_180,
-       .scale_float                    = {
-               .ival                   = 0,
-               .fval                   = 100000,
-       }
+static struct bmp_hal_dev bmp_hal_dev_180[] = {
+       {
+               .version                = 1,
+               .scale_n                = ARRAY_SIZE(bmp_scale_prs_180),
+               .scale                  = bmp_scale_prs_180,
+               .scale_float            = {
+                       .ival           = 0,
+                       .fval           = 10000,
+               },
+       },
+       {
+               .version                = 1,
+               .scale_n                = ARRAY_SIZE(bmp_scale_tmp_180),
+               .scale                  = bmp_scale_tmp_180,
+               .scale_float            = {
+                       .ival           = 0,
+                       .fval           = 100000,
+               }
+       },
 };
 
 static struct bmp_hal bmp_hal_180 = {
-       .p                              = &bmp_hal_dev_pres_180,
-       .t                              = &bmp_hal_dev_temp_180,
+       .dev                            = bmp_hal_dev_180,
        .part                           = BMP180_NAME,
        .rom_addr_start                 = BMP180_REG_AC1,
        .rom_size                       = 22,
@@ -1425,33 +1528,42 @@ static struct bmp_hal bmp_hal_180 = {
        .mode_mask                      = BMP180_REG_CTRL_MODE_MASK,
        .cmode_tbl                      = NULL,
        .bmp_read                       = &bmp_read_180,
+#if BMP_NVI_MPU_SUPPORT
+       .mpu_id                         = 0,
+       .port_rd_reg                    = BMP_REG_CTRL,
+       .port_rd_ctrl                   = 6,
+       .port_rd_handler                = &bmp_mpu_handler_180,
+#endif /* BMP_NVI_MPU_SUPPORT */
 };
 
-static struct bmp_scale bmp_scale_pres_280[] = {
+static struct bmp_scale bmp_scale_prs_280[] = {
        {
-               .delay_ms               = 9,
+               .delay_ms               = 44,
+               .os                     = 0x05,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 28700,
+                       .fval           = 1800,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 2740,
+                       .fval           = 24800,
                },
        },
        {
-               .delay_ms               = 12,
+               .delay_ms               = 23,
+               .os                     = 0x04,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 14300,
+                       .fval           = 3600,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 4170,
+                       .fval           = 12700,
                },
        },
        {
-               .delay_ms               = 18,
+               .delay_ms               = 14,
+               .os                     = 0x03,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 7200,
@@ -1462,54 +1574,60 @@ static struct bmp_scale bmp_scale_pres_280[] = {
                },
        },
        {
-               .delay_ms               = 30,
+               .delay_ms               = 9,
+               .os                     = 0x02,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 3600,
+                       .fval           = 14300,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 12700,
+                       .fval           = 4170,
                },
        },
        {
-               .delay_ms               = 57,
+               .delay_ms               = 7,
+               .os                     = 0x01,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 1800,
+                       .fval           = 28700,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 24800,
+                       .fval           = 2740,
                },
        },
 };
 
-static struct bmp_scale bmp_scale_temp_280[] = {
+static struct bmp_scale bmp_scale_tmp_280[] = {
+       /* os oversampling is useless > 2x and only used for pressure @ 16x */
        {
-               .delay_ms               = 9,
+               .delay_ms               = 44,
+               .os                     = 0x02,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 5000,
+                       .fval           = 300,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 2740,
+                       .fval           = 24800,
                },
        },
        {
-               .delay_ms               = 12,
+               .delay_ms               = 23,
+               .os                     = 0x01,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 2500,
+                       .fval           = 600,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 4170,
+                       .fval           = 12700,
                },
        },
        {
-               .delay_ms               = 18,
+               .delay_ms               = 14,
+               .os                     = 0x01,
                .resolution             = {
                        .ival           = 0,
                        .fval           = 1200,
@@ -1520,49 +1638,50 @@ static struct bmp_scale bmp_scale_temp_280[] = {
                },
        },
        {
-               .delay_ms               = 30,
+               .delay_ms               = 9,
+               .os                     = 0x01,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 600,
+                       .fval           = 2500,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 12700,
+                       .fval           = 4170,
                },
        },
        {
-               .delay_ms               = 57,
+               .delay_ms               = 7,
+               .os                     = 0x01,
                .resolution             = {
                        .ival           = 0,
-                       .fval           = 300,
+                       .fval           = 5000,
                },
                .milliamp               = {
                        .ival           = 0,
-                       .fval           = 24800,
+                       .fval           = 2740,
                },
        },
 };
 
-static struct bmp_hal_dev bmp_hal_dev_pres_280 = {
-       .version                        = 1,
-       .scale_i_max                    = ARRAY_SIZE(bmp_scale_pres_280),
-       .scale_dflt                     = BMP280_RANGE_DFLT,
-       .scale                          = bmp_scale_pres_280,
-       .scale_float                    = {
-               .ival                   = 0,
-               .fval                   = 10000,
-       }
-};
-
-static struct bmp_hal_dev bmp_hal_dev_temp_280 = {
-       .version                        = 1,
-       .scale_i_max                    = ARRAY_SIZE(bmp_scale_temp_280),
-       .scale_dflt                     = BMP280_RANGE_DFLT,
-       .scale                          = bmp_scale_temp_280,
-       .scale_float                    = {
-               .ival                   = 0,
-               .fval                   = 10000,
-       }
+static struct bmp_hal_dev bmp_hal_dev_280[] = {
+       {
+               .version                = 1,
+               .scale_n                = ARRAY_SIZE(bmp_scale_prs_280),
+               .scale                  = bmp_scale_prs_280,
+               .scale_float            = {
+                       .ival           = 0,
+                       .fval           = 10000,
+               }
+       },
+       {
+               .version                = 1,
+               .scale_n                = ARRAY_SIZE(bmp_scale_tmp_280),
+               .scale                  = bmp_scale_tmp_280,
+               .scale_float            = {
+                       .ival           = 0,
+                       .fval           = 10000,
+               },
+       },
 };
 
 static struct bmp_cmode bmp_cmode_280[] = {
@@ -1602,8 +1721,7 @@ static struct bmp_cmode bmp_cmode_280[] = {
 };
 
 static struct bmp_hal bmp_hal_280 = {
-       .p                              = &bmp_hal_dev_pres_280,
-       .t                              = &bmp_hal_dev_temp_280,
+       .dev                            = bmp_hal_dev_280,
        .part                           = BMP280_NAME,
        .rom_addr_start                 = BMP280_REG_CWORD00,
        .rom_size                       = 26,
@@ -1613,6 +1731,9 @@ static struct bmp_hal bmp_hal_280 = {
        .bmp_read                       = &bmp_read_280,
 #if BMP_NVI_MPU_SUPPORT
        .mpu_id                         = PRESSURE_ID_BMP280,
+       .port_rd_reg                    = BMP280_REG_STATUS,
+       .port_rd_ctrl                   = 10,
+       .port_rd_handler                = &bmp_mpu_handler_280,
 #endif /* BMP_NVI_MPU_SUPPORT */
 };
 
@@ -1637,38 +1758,20 @@ static int bmp_id_hal(struct bmp_state *st)
                break;
        }
 
-       st->scale_user = st->hal->p->scale_dflt;
+       /* default scale to fastest and least power usage */
+       st->scale_user = st->hal->dev[BMP_DEV_PRS].scale_n;
+       st->scale_i = st->scale_user - 1;
+       if (st->hal->cmode_tbl == NULL)
+               st->cmode = false;
        for (i = 0; i < BMP_DEV_N; i++)
                memcpy(&st->cfg[i], &bmp_cfg_dflt[i],
                       sizeof(struct sensor_cfg));
-       st->cfg[BMP_DEV_PRES].part = st->hal->part;
-       st->cfg[BMP_DEV_PRES].version = st->hal->p->version;
-       st->cfg[BMP_DEV_PRES].resolution.ival =
-                               st->hal->p->scale[st->scale_i].resolution.ival;
-       st->cfg[BMP_DEV_PRES].resolution.fval =
-                               st->hal->p->scale[st->scale_i].resolution.fval;
-       st->cfg[BMP_DEV_PRES].milliamp.ival =
-                                 st->hal->p->scale[st->scale_i].milliamp.ival;
-       st->cfg[BMP_DEV_PRES].milliamp.fval =
-                                 st->hal->p->scale[st->scale_i].milliamp.fval;
-       st->cfg[BMP_DEV_PRES].delay_us_min =
-                               st->hal->p->scale[st->scale_i].delay_ms * 1000;
-       st->cfg[BMP_DEV_PRES].scale.ival = st->hal->p->scale_float.ival;
-       st->cfg[BMP_DEV_PRES].scale.fval = st->hal->p->scale_float.fval;
-       st->cfg[BMP_DEV_TEMP].part = st->hal->part;
-       st->cfg[BMP_DEV_TEMP].version = st->hal->t->version;
-       st->cfg[BMP_DEV_TEMP].resolution.ival =
-                               st->hal->t->scale[st->scale_i].resolution.ival;
-       st->cfg[BMP_DEV_TEMP].resolution.fval =
-                               st->hal->t->scale[st->scale_i].resolution.fval;
-       st->cfg[BMP_DEV_TEMP].milliamp.ival =
-                                 st->hal->t->scale[st->scale_i].milliamp.ival;
-       st->cfg[BMP_DEV_TEMP].milliamp.fval =
-                                 st->hal->t->scale[st->scale_i].milliamp.fval;
-       st->cfg[BMP_DEV_TEMP].delay_us_min =
-                               st->hal->t->scale[st->scale_i].delay_ms * 1000;
-       st->cfg[BMP_DEV_TEMP].scale.ival = st->hal->t->scale_float.ival;
-       st->cfg[BMP_DEV_TEMP].scale.fval = st->hal->t->scale_float.fval;
+       for (i = 0; i < BMP_DEV_N; i++) {
+               st->cfg[i].part = st->hal->part;
+               st->cfg[i].version = st->hal->dev[i].version;
+               st->cfg[i].scale.ival = st->hal->dev[i].scale_float.ival;
+               st->cfg[i].scale.fval = st->hal->dev[i].scale_float.fval;
+       }
        return ret;
 }
 
@@ -1705,6 +1808,8 @@ static int bmp_id_dev(struct bmp_state *st, const char *name)
 {
 #if BMP_NVI_MPU_SUPPORT
        struct nvi_mpu_port nmp;
+       struct nvi_mpu_inf inf;
+       unsigned int i;
        u8 config_boot;
 #endif /* BMP_NVI_MPU_SUPPORT */
        u8 val = 0;
@@ -1740,45 +1845,49 @@ static int bmp_id_dev(struct bmp_state *st, const char *name)
        if (config_boot == NVI_CONFIG_BOOT_MPU) {
                st->mpu_en = true;
                bmp_id_hal(st);
-               if (st->hal->cmode_tbl == NULL || !st->i2c->irq) {
-                       nmp.addr = st->i2c_addr;
-                       nmp.reg = BMP_REG_CTRL;
-                       nmp.ctrl = 1;
-                       nmp.data_out = st->data_out;
-                       nmp.delay_ms = st->hal->p->scale[st->scale_i].delay_ms;
-                       nmp.delay_us = 0;
-                       nmp.shutdown_bypass = false;
-                       nmp.handler = NULL;
-                       nmp.ext_driver = NULL;
-                       ret = nvi_mpu_port_alloc(&nmp, 2);
-                       dev_dbg(&st->i2c->dev, "%s MPU port/ret=%d\n",
-                               __func__, ret);
-                       if (ret < 0)
+               nmp.type = SECONDARY_SLAVE_TYPE_PRESSURE;
+               nmp.id = st->hal->mpu_id;
+               nmp.addr = st->i2c_addr; /* write port */
+               nmp.reg = BMP_REG_CTRL;
+               nmp.ctrl = 1;
+               nmp.data_out = st->data_out;
+               nmp.delay_ms = st->hal->dev[BMP_DEV_PRS].
+                                                  scale[st->scale_i].delay_ms;
+               nmp.period_us = 0;
+               nmp.shutdown_bypass = false;
+               nmp.handler = NULL;
+               nmp.ext_driver = NULL;
+               ret = nvi_mpu_port_alloc(&nmp);
+               dev_dbg(&st->i2c->dev, "%s MPU port/ret=%d\n",
+                       __func__, ret);
+               /* By requesting the write port first it allows us to
+                * automatically determine if the DMP requires a single
+                * port, in which case this port request will fail.
+                * If this part does not support continuous mode
+                * required for single port operation, then this device
+                * population fails.
+                */
+               if (ret < 0) {
+                       if (st->hal->cmode_tbl)
+                               st->cmode = true;
+                       else
                                return ret;
-
+               } else {
+                       st->cmode = false;
                        st->port_id[WR] = ret;
                }
-               nmp.addr = st->i2c_addr | 0x80;
+
+               nmp.addr = st->i2c_addr | 0x80; /* read port */
                nmp.data_out = 0;
                nmp.delay_ms = 0;
-               nmp.delay_us = st->poll_delay_us;
-               if ((st->hal->cmode_tbl != NULL) && st->i2c->irq)
+               nmp.period_us = st->poll_delay_us;
+               if (st->cmode)
                        nmp.shutdown_bypass = true;
-               else
-                       nmp.shutdown_bypass = false;
                nmp.ext_driver = (void *)st;
-               if (st->dev_id == BMP_REG_ID_BMP180) {
-                       nmp.reg = BMP_REG_CTRL;
-                       nmp.ctrl = 6; /* MPU FIFO can't handle odd size */
-                       nmp.handler = &bmp_mpu_handler_180;
-               } else {
-                       nmp.reg = BMP280_REG_STATUS;
-                       nmp.ctrl = 10; /* MPU FIFO can't handle odd size */
-                       nmp.handler = &bmp_mpu_handler_280;
-               }
-               nmp.type = SECONDARY_SLAVE_TYPE_PRESSURE;
-               nmp.id = st->hal->mpu_id;
-               ret = nvi_mpu_port_alloc(&nmp, 3);
+               nmp.reg = st->hal->port_rd_reg;
+               nmp.ctrl = st->hal->port_rd_ctrl;
+               nmp.handler = st->hal->port_rd_handler;
+               ret = nvi_mpu_port_alloc(&nmp);
                dev_dbg(&st->i2c->dev, "%s MPU port/ret=%d\n",
                        __func__, ret);
                if (ret < 0) {
@@ -1789,13 +1898,18 @@ static int bmp_id_dev(struct bmp_state *st, const char *name)
                }
 
                st->port_id[RD] = ret;
-               nvi_mpu_fifo(st->port_id[RD],
-                            &st->cfg[BMP_DEV_PRES].fifo_rsrv_evnt_cnt,
-                            &st->cfg[BMP_DEV_PRES].fifo_max_evnt_cnt);
-               st->cfg[BMP_DEV_TEMP].fifo_rsrv_evnt_cnt =
-                                     st->cfg[BMP_DEV_PRES].fifo_rsrv_evnt_cnt;
-               st->cfg[BMP_DEV_TEMP].fifo_max_evnt_cnt =
-                                      st->cfg[BMP_DEV_PRES].fifo_max_evnt_cnt;
+               ret = nvi_mpu_info(st->port_id[RD], &inf);
+               if (ret)
+                       return ret;
+
+               st->period_us_min = inf.period_us_min;
+               for (i = 0; i < BMP_DEV_N; i++) {
+                       st->cfg[i].fifo_rsrv_evnt_cnt = inf.fifo_reserve;
+                       st->cfg[i].fifo_max_evnt_cnt = inf.fifo_max;
+                       st->cfg[i].delay_us_max = inf.period_us_max;
+               }
+               st->dmp_rd_len_sts = inf.dmp_rd_len_sts;
+               st->dmp_rd_len_data = inf.dmp_rd_len_data;
                return 0;
        }
 #endif /* BMP_NVI_MPU_SUPPORT */
@@ -1852,7 +1966,7 @@ static int bmp_of_dt(struct bmp_state *st, struct device_node *dn)
                        return -ENODEV;
 
                /* this device supports these programmable parameters */
-               if (!(of_property_read_string(dn, "nvi_config", &pchar))) {
+               if (!of_property_read_string(dn, "nvi_config", &pchar)) {
                        for (cfg = 0; cfg < ARRAY_SIZE(bmp_configs); cfg++) {
                                if (!strcasecmp(pchar, bmp_configs[cfg])) {
                                        st->nvi_config = cfg;
@@ -1860,8 +1974,14 @@ static int bmp_of_dt(struct bmp_state *st, struct device_node *dn)
                                }
                        }
                }
-       }
 
+               if (!of_property_read_u8(dn, "cmode_enable", &cfg)) {
+                       if (cfg)
+                               st->cmode = true;
+                       else
+                               st->cmode = false;
+               }
+       }
        return 0;
 }
 
@@ -1870,6 +1990,7 @@ static int bmp_probe(struct i2c_client *client,
 {
        struct bmp_state *st;
        unsigned int i;
+       unsigned int n;
        int ret;
 
        dev_info(&client->dev, "%s %s\n", id->name, __func__);
@@ -1895,7 +2016,7 @@ static int bmp_probe(struct i2c_client *client,
        bmp_pm_init(st);
        ret = bmp_id_i2c(st, id);
        if (ret == -EAGAIN)
-               goto bmp_probe_again;
+               goto bmp_probe_exit;
        else if (ret)
                goto bmp_probe_err;
 
@@ -1909,26 +2030,34 @@ static int bmp_probe(struct i2c_client *client,
                goto bmp_probe_err;
        }
 
+       st->cfg[BMP_DEV_PRS].resolution.ival = st->scale_user;
+       nvs_of_dt(client->dev.of_node, &st->cfg[BMP_DEV_PRS], NULL);
+       bmp_resolution(st, BMP_DEV_PRS, st->cfg[BMP_DEV_PRS].resolution.ival);
+       nvs_of_dt(client->dev.of_node, &st->cfg[BMP_DEV_TMP], NULL);
+       if (st->cfg[BMP_DEV_PRS].snsr_id < 0)
+               /* pressure disabled so use temperature settings */
+               bmp_resolution(st, BMP_DEV_PRS,
+                              st->cfg[BMP_DEV_TMP].resolution.ival);
+       n = 0;
        for (i = 0; i < BMP_DEV_N; i++) {
-               nvs_of_dt(client->dev.of_node, &st->cfg[i], NULL);
-               ret |= st->nvs->probe(&st->nvs_st[i], st, &client->dev,
-                                     &bmp_fn_dev, &st->cfg[i]);
+               ret = st->nvs->probe(&st->nvs_st[i], st, &client->dev,
+                                    &bmp_fn_dev, &st->cfg[i]);
+               if (!ret)
+                       n++;
        }
-       if (ret) {
-               dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
+       if (!n) {
                ret = -ENODEV;
-               goto bmp_probe_err;
+               goto bmp_probe_exit;
        }
 
        if (!st->mpu_en)
                INIT_DELAYED_WORK(&st->dw, bmp_work);
-
        dev_info(&client->dev, "%s done\n", __func__);
        return 0;
 
 bmp_probe_err:
        dev_err(&client->dev, "%s ERR %d\n", __func__, ret);
-bmp_probe_again:
+bmp_probe_exit:
        bmp_remove(client);
        return ret;
 }